{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"provenance":[],"authorship_tag":"ABX9TyP8abIrW94IN5ve0HZuRw4r"},"kernelspec":{"name":"python3","display_name":"Python 3"},"language_info":{"name":"python"}},"cells":[{"cell_type":"markdown","source":["quick-start"],"metadata":{"id":"gzcxCHG2VZd7"}},{"cell_type":"markdown","source":["# Part 1: 创建一个基础的聊天机器人"],"metadata":{"id":"ZhJ7W9m1i7S6"}},{"cell_type":"code","execution_count":null,"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"h2pDVG2zlFZn","executionInfo":{"status":"ok","timestamp":1722150011236,"user_tz":-480,"elapsed":17775,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"72401e0c-3eb4-4e4d-e969-06f0e81c78ac","collapsed":true},"outputs":[{"output_type":"stream","name":"stdout","text":["Collecting langgraph==0.1.8\n","  Downloading langgraph-0.1.8-py3-none-any.whl.metadata (13 kB)\n","Collecting langsmith\n","  Downloading langsmith-0.1.93-py3-none-any.whl.metadata (13 kB)\n","Collecting langchain-openai\n","  Downloading langchain_openai-0.1.19-py3-none-any.whl.metadata (2.6 kB)\n","Collecting langchain_community\n","  Downloading langchain_community-0.2.10-py3-none-any.whl.metadata (2.7 kB)\n","Collecting langchain-core<0.3,>=0.2.15 (from langgraph==0.1.8)\n","  Downloading langchain_core-0.2.24-py3-none-any.whl.metadata (6.2 kB)\n","Collecting orjson<4.0.0,>=3.9.14 (from langsmith)\n","  Downloading orjson-3.10.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (50 kB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m50.4/50.4 kB\u001b[0m \u001b[31m1.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hRequirement already satisfied: pydantic<3,>=1 in /usr/local/lib/python3.10/dist-packages (from langsmith) (2.8.2)\n","Requirement already satisfied: requests<3,>=2 in /usr/local/lib/python3.10/dist-packages (from langsmith) (2.31.0)\n","Collecting openai<2.0.0,>=1.32.0 (from langchain-openai)\n","  Downloading openai-1.37.1-py3-none-any.whl.metadata (22 kB)\n","Collecting tiktoken<1,>=0.7 (from langchain-openai)\n","  Downloading tiktoken-0.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (6.6 kB)\n","Requirement already satisfied: PyYAML>=5.3 in /usr/local/lib/python3.10/dist-packages (from langchain_community) (6.0.1)\n","Requirement already satisfied: SQLAlchemy<3,>=1.4 in /usr/local/lib/python3.10/dist-packages (from langchain_community) (2.0.31)\n","Requirement already satisfied: aiohttp<4.0.0,>=3.8.3 in /usr/local/lib/python3.10/dist-packages (from langchain_community) (3.9.5)\n","Collecting dataclasses-json<0.7,>=0.5.7 (from langchain_community)\n","  Downloading dataclasses_json-0.6.7-py3-none-any.whl.metadata (25 kB)\n","Collecting langchain<0.3.0,>=0.2.9 (from langchain_community)\n","  Downloading langchain-0.2.11-py3-none-any.whl.metadata (7.1 kB)\n","Requirement already satisfied: numpy<2,>=1 in /usr/local/lib/python3.10/dist-packages (from langchain_community) (1.25.2)\n","Requirement already satisfied: tenacity!=8.4.0,<9.0.0,>=8.1.0 in /usr/local/lib/python3.10/dist-packages (from langchain_community) (8.5.0)\n","Requirement already satisfied: aiosignal>=1.1.2 in /usr/local/lib/python3.10/dist-packages (from aiohttp<4.0.0,>=3.8.3->langchain_community) (1.3.1)\n","Requirement already satisfied: attrs>=17.3.0 in /usr/local/lib/python3.10/dist-packages (from aiohttp<4.0.0,>=3.8.3->langchain_community) (23.2.0)\n","Requirement already satisfied: frozenlist>=1.1.1 in /usr/local/lib/python3.10/dist-packages (from aiohttp<4.0.0,>=3.8.3->langchain_community) (1.4.1)\n","Requirement already satisfied: multidict<7.0,>=4.5 in /usr/local/lib/python3.10/dist-packages (from aiohttp<4.0.0,>=3.8.3->langchain_community) (6.0.5)\n","Requirement already satisfied: yarl<2.0,>=1.0 in /usr/local/lib/python3.10/dist-packages (from aiohttp<4.0.0,>=3.8.3->langchain_community) (1.9.4)\n","Requirement already satisfied: async-timeout<5.0,>=4.0 in /usr/local/lib/python3.10/dist-packages (from aiohttp<4.0.0,>=3.8.3->langchain_community) (4.0.3)\n","Collecting marshmallow<4.0.0,>=3.18.0 (from dataclasses-json<0.7,>=0.5.7->langchain_community)\n","  Downloading marshmallow-3.21.3-py3-none-any.whl.metadata (7.1 kB)\n","Collecting typing-inspect<1,>=0.4.0 (from dataclasses-json<0.7,>=0.5.7->langchain_community)\n","  Downloading typing_inspect-0.9.0-py3-none-any.whl.metadata (1.5 kB)\n","Collecting langchain-text-splitters<0.3.0,>=0.2.0 (from langchain<0.3.0,>=0.2.9->langchain_community)\n","  Downloading langchain_text_splitters-0.2.2-py3-none-any.whl.metadata (2.1 kB)\n","Collecting jsonpatch<2.0,>=1.33 (from langchain-core<0.3,>=0.2.15->langgraph==0.1.8)\n","  Downloading jsonpatch-1.33-py2.py3-none-any.whl.metadata (3.0 kB)\n","Requirement already satisfied: packaging<25,>=23.2 in /usr/local/lib/python3.10/dist-packages (from langchain-core<0.3,>=0.2.15->langgraph==0.1.8) (24.1)\n","Requirement already satisfied: anyio<5,>=3.5.0 in /usr/local/lib/python3.10/dist-packages (from openai<2.0.0,>=1.32.0->langchain-openai) (3.7.1)\n","Requirement already satisfied: distro<2,>=1.7.0 in /usr/lib/python3/dist-packages (from openai<2.0.0,>=1.32.0->langchain-openai) (1.7.0)\n","Collecting httpx<1,>=0.23.0 (from openai<2.0.0,>=1.32.0->langchain-openai)\n","  Downloading httpx-0.27.0-py3-none-any.whl.metadata (7.2 kB)\n","Requirement already satisfied: sniffio in /usr/local/lib/python3.10/dist-packages (from openai<2.0.0,>=1.32.0->langchain-openai) (1.3.1)\n","Requirement already satisfied: tqdm>4 in /usr/local/lib/python3.10/dist-packages (from openai<2.0.0,>=1.32.0->langchain-openai) (4.66.4)\n","Requirement already satisfied: typing-extensions<5,>=4.7 in /usr/local/lib/python3.10/dist-packages (from openai<2.0.0,>=1.32.0->langchain-openai) (4.12.2)\n","Requirement already satisfied: annotated-types>=0.4.0 in /usr/local/lib/python3.10/dist-packages (from pydantic<3,>=1->langsmith) (0.7.0)\n","Requirement already satisfied: pydantic-core==2.20.1 in /usr/local/lib/python3.10/dist-packages (from pydantic<3,>=1->langsmith) (2.20.1)\n","Requirement already satisfied: charset-normalizer<4,>=2 in /usr/local/lib/python3.10/dist-packages (from requests<3,>=2->langsmith) (3.3.2)\n","Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.10/dist-packages (from requests<3,>=2->langsmith) (3.7)\n","Requirement already satisfied: urllib3<3,>=1.21.1 in /usr/local/lib/python3.10/dist-packages (from requests<3,>=2->langsmith) (2.0.7)\n","Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.10/dist-packages (from requests<3,>=2->langsmith) (2024.7.4)\n","Requirement already satisfied: greenlet!=0.4.17 in /usr/local/lib/python3.10/dist-packages (from SQLAlchemy<3,>=1.4->langchain_community) (3.0.3)\n","Requirement already satisfied: regex>=2022.1.18 in /usr/local/lib/python3.10/dist-packages (from tiktoken<1,>=0.7->langchain-openai) (2024.5.15)\n","Requirement already satisfied: exceptiongroup in /usr/local/lib/python3.10/dist-packages (from anyio<5,>=3.5.0->openai<2.0.0,>=1.32.0->langchain-openai) (1.2.2)\n","Collecting httpcore==1.* (from httpx<1,>=0.23.0->openai<2.0.0,>=1.32.0->langchain-openai)\n","  Downloading httpcore-1.0.5-py3-none-any.whl.metadata (20 kB)\n","Collecting h11<0.15,>=0.13 (from httpcore==1.*->httpx<1,>=0.23.0->openai<2.0.0,>=1.32.0->langchain-openai)\n","  Downloading h11-0.14.0-py3-none-any.whl.metadata (8.2 kB)\n","Collecting jsonpointer>=1.9 (from jsonpatch<2.0,>=1.33->langchain-core<0.3,>=0.2.15->langgraph==0.1.8)\n","  Downloading jsonpointer-3.0.0-py2.py3-none-any.whl.metadata (2.3 kB)\n","Collecting mypy-extensions>=0.3.0 (from typing-inspect<1,>=0.4.0->dataclasses-json<0.7,>=0.5.7->langchain_community)\n","  Downloading mypy_extensions-1.0.0-py3-none-any.whl.metadata (1.1 kB)\n","Downloading langgraph-0.1.8-py3-none-any.whl (91 kB)\n","\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m91.4/91.4 kB\u001b[0m \u001b[31m6.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hDownloading langsmith-0.1.93-py3-none-any.whl (139 kB)\n","\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m139.8/139.8 kB\u001b[0m \u001b[31m11.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hDownloading langchain_openai-0.1.19-py3-none-any.whl (47 kB)\n","\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m47.1/47.1 kB\u001b[0m \u001b[31m3.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hDownloading langchain_community-0.2.10-py3-none-any.whl (2.3 MB)\n","\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.3/2.3 MB\u001b[0m \u001b[31m34.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hDownloading dataclasses_json-0.6.7-py3-none-any.whl (28 kB)\n","Downloading langchain-0.2.11-py3-none-any.whl (990 kB)\n","\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m990.3/990.3 kB\u001b[0m \u001b[31m31.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hDownloading langchain_core-0.2.24-py3-none-any.whl (377 kB)\n","\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m377.3/377.3 kB\u001b[0m \u001b[31m19.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hDownloading openai-1.37.1-py3-none-any.whl (337 kB)\n","\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m337.0/337.0 kB\u001b[0m \u001b[31m16.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hDownloading orjson-3.10.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (141 kB)\n","\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m141.1/141.1 kB\u001b[0m \u001b[31m8.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hDownloading tiktoken-0.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.1 MB)\n","\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.1/1.1 MB\u001b[0m \u001b[31m38.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hDownloading httpx-0.27.0-py3-none-any.whl (75 kB)\n","\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m75.6/75.6 kB\u001b[0m \u001b[31m5.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hDownloading httpcore-1.0.5-py3-none-any.whl (77 kB)\n","\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m77.9/77.9 kB\u001b[0m \u001b[31m5.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hDownloading jsonpatch-1.33-py2.py3-none-any.whl (12 kB)\n","Downloading langchain_text_splitters-0.2.2-py3-none-any.whl (25 kB)\n","Downloading marshmallow-3.21.3-py3-none-any.whl (49 kB)\n","\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m49.2/49.2 kB\u001b[0m \u001b[31m3.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hDownloading typing_inspect-0.9.0-py3-none-any.whl (8.8 kB)\n","Downloading jsonpointer-3.0.0-py2.py3-none-any.whl (7.6 kB)\n","Downloading mypy_extensions-1.0.0-py3-none-any.whl (4.7 kB)\n","Downloading h11-0.14.0-py3-none-any.whl (58 kB)\n","\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m58.3/58.3 kB\u001b[0m \u001b[31m3.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hInstalling collected packages: orjson, mypy-extensions, marshmallow, jsonpointer, h11, typing-inspect, tiktoken, jsonpatch, httpcore, langsmith, httpx, dataclasses-json, openai, langchain-core, langgraph, langchain-text-splitters, langchain-openai, langchain, langchain_community\n","Successfully installed dataclasses-json-0.6.7 h11-0.14.0 httpcore-1.0.5 httpx-0.27.0 jsonpatch-1.33 jsonpointer-3.0.0 langchain-0.2.11 langchain-core-0.2.24 langchain-openai-0.1.19 langchain-text-splitters-0.2.2 langchain_community-0.2.10 langgraph-0.1.8 langsmith-0.1.93 marshmallow-3.21.3 mypy-extensions-1.0.0 openai-1.37.1 orjson-3.10.6 tiktoken-0.7.0 typing-inspect-0.9.0\n"]}],"source":["pip install -U langgraph==0.1.8 langsmith langchain-openai langchain_community"]},{"cell_type":"code","source":["pip list"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"collapsed":true,"id":"1XKQvxApgTqR","executionInfo":{"status":"ok","timestamp":1721567544487,"user_tz":-480,"elapsed":1461,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"faf9163e-32d0-4b03-b968-6d41033fb4c9"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Package                          Version\n","-------------------------------- ---------------------\n","absl-py                          1.4.0\n","accelerate                       0.32.1\n","aiohttp                          3.9.5\n","aiosignal                        1.3.1\n","alabaster                        0.7.16\n","albumentations                   1.3.1\n","altair                           4.2.2\n","annotated-types                  0.7.0\n","anyio                            3.7.1\n","argon2-cffi                      23.1.0\n","argon2-cffi-bindings             21.2.0\n","array_record                     0.5.1\n","arviz                            0.15.1\n","astropy                          5.3.4\n","astunparse                       1.6.3\n","async-timeout                    4.0.3\n","atpublic                         4.1.0\n","attrs                            23.2.0\n","audioread                        3.0.1\n","autograd                         1.6.2\n","Babel                            2.15.0\n","backcall                         0.2.0\n","beautifulsoup4                   4.12.3\n","bidict                           0.23.1\n","bigframes                        1.11.1\n","bleach                           6.1.0\n","blinker                          1.4\n","blis                             0.7.11\n","blosc2                           2.0.0\n","bokeh                            3.3.4\n","bqplot                           0.12.43\n","branca                           0.7.2\n","build                            1.2.1\n","CacheControl                     0.14.0\n","cachetools                       5.4.0\n","catalogue                        2.0.10\n","certifi                          2024.7.4\n","cffi                             1.16.0\n","chardet                          5.2.0\n","charset-normalizer               3.3.2\n","chex                             0.1.86\n","click                            8.1.7\n","click-plugins                    1.1.1\n","cligj                            0.7.2\n","cloudpathlib                     0.18.1\n","cloudpickle                      2.2.1\n","cmake                            3.27.9\n","cmdstanpy                        1.2.4\n","colorcet                         3.1.0\n","colorlover                       0.3.0\n","colour                           0.1.5\n","community                        1.0.0b1\n","confection                       0.1.5\n","cons                             0.4.6\n","contextlib2                      21.6.0\n","contourpy                        1.2.1\n","cryptography                     42.0.8\n","cuda-python                      12.2.1\n","cudf-cu12                        24.4.1\n","cufflinks                        0.17.3\n","cupy-cuda12x                     12.2.0\n","cvxopt                           1.3.2\n","cvxpy                            1.3.4\n","cycler                           0.12.1\n","cymem                            2.0.8\n","Cython                           3.0.10\n","dask                             2023.8.1\n","dataclasses-json                 0.6.7\n","datascience                      0.17.6\n","db-dtypes                        1.2.0\n","dbus-python                      1.2.18\n","debugpy                          1.6.6\n","decorator                        4.4.2\n","defusedxml                       0.7.1\n","distributed                      2023.8.1\n","distro                           1.7.0\n","dlib                             19.24.4\n","dm-tree                          0.1.8\n","docstring_parser                 0.16\n","docutils                         0.18.1\n","dopamine_rl                      4.0.9\n","duckdb                           0.10.3\n","earthengine-api                  0.1.411\n","easydict                         1.13\n","ecos                             2.0.14\n","editdistance                     0.6.2\n","eerepr                           0.0.4\n","en-core-web-sm                   3.7.1\n","entrypoints                      0.4\n","et-xmlfile                       1.1.0\n","etils                            1.7.0\n","etuples                          0.3.9\n","exceptiongroup                   1.2.2\n","fastai                           2.7.15\n","fastcore                         1.5.54\n","fastdownload                     0.0.7\n","fastjsonschema                   2.20.0\n","fastprogress                     1.0.3\n","fastrlock                        0.8.2\n","filelock                         3.15.4\n","fiona                            1.9.6\n","firebase-admin                   5.3.0\n","Flask                            2.2.5\n","flatbuffers                      24.3.25\n","flax                             0.8.4\n","folium                           0.14.0\n","fonttools                        4.53.1\n","frozendict                       2.4.4\n","frozenlist                       1.4.1\n","fsspec                           2023.6.0\n","future                           0.18.3\n","gast                             0.6.0\n","gcsfs                            2023.6.0\n","GDAL                             3.6.4\n","gdown                            5.1.0\n","geemap                           0.33.0\n","gensim                           4.3.2\n","geocoder                         1.38.1\n","geographiclib                    2.0\n","geopandas                        0.13.2\n","geopy                            2.3.0\n","gin-config                       0.5.0\n","glob2                            0.7\n","google                           2.0.3\n","google-ai-generativelanguage     0.6.4\n","google-api-core                  2.16.2\n","google-api-python-client         2.84.0\n","google-auth                      2.27.0\n","google-auth-httplib2             0.1.1\n","google-auth-oauthlib             1.2.1\n","google-cloud-aiplatform          1.59.0\n","google-cloud-bigquery            3.21.0\n","google-cloud-bigquery-connection 1.12.1\n","google-cloud-bigquery-storage    2.25.0\n","google-cloud-bigtable            2.24.0\n","google-cloud-core                2.3.3\n","google-cloud-datastore           2.15.2\n","google-cloud-firestore           2.11.1\n","google-cloud-functions           1.13.3\n","google-cloud-iam                 2.15.1\n","google-cloud-language            2.13.4\n","google-cloud-pubsub              2.22.0\n","google-cloud-resource-manager    1.12.4\n","google-cloud-storage             2.8.0\n","google-cloud-translate           3.11.3\n","google-colab                     1.0.0\n","google-crc32c                    1.5.0\n","google-generativeai              0.5.4\n","google-pasta                     0.2.0\n","google-resumable-media           2.7.1\n","googleapis-common-protos         1.63.2\n","googledrivedownloader            0.4\n","graphviz                         0.20.3\n","greenlet                         3.0.3\n","grpc-google-iam-v1               0.13.1\n","grpcio                           1.64.1\n","grpcio-status                    1.48.2\n","gspread                          6.0.2\n","gspread-dataframe                3.3.1\n","gym                              0.25.2\n","gym-notices                      0.0.8\n","h11                              0.14.0\n","h5netcdf                         1.3.0\n","h5py                             3.9.0\n","holidays                         0.53\n","holoviews                        1.17.1\n","html5lib                         1.1\n","httpcore                         1.0.5\n","httpimport                       1.3.1\n","httplib2                         0.22.0\n","httpx                            0.27.0\n","huggingface-hub                  0.23.5\n","humanize                         4.7.0\n","hyperopt                         0.2.7\n","ibis-framework                   8.0.0\n","idna                             3.7\n","imageio                          2.31.6\n","imageio-ffmpeg                   0.5.1\n","imagesize                        1.4.1\n","imbalanced-learn                 0.10.1\n","imgaug                           0.4.0\n","immutabledict                    4.2.0\n","importlib_metadata               8.0.0\n","importlib_resources              6.4.0\n","imutils                          0.5.4\n","inflect                          7.0.0\n","iniconfig                        2.0.0\n","intel-openmp                     2023.2.4\n","ipyevents                        2.0.2\n","ipyfilechooser                   0.6.0\n","ipykernel                        5.5.6\n","ipyleaflet                       0.18.2\n","ipyparallel                      8.8.0\n","ipython                          7.34.0\n","ipython-genutils                 0.2.0\n","ipython-sql                      0.5.0\n","ipytree                          0.2.2\n","ipywidgets                       7.7.1\n","itsdangerous                     2.2.0\n","jax                              0.4.26\n","jaxlib                           0.4.26+cuda12.cudnn89\n","jeepney                          0.7.1\n","jellyfish                        1.0.4\n","jieba                            0.42.1\n","Jinja2                           3.1.4\n","joblib                           1.4.2\n","jsonpatch                        1.33\n","jsonpickle                       3.2.2\n","jsonpointer                      3.0.0\n","jsonschema                       4.19.2\n","jsonschema-specifications        2023.12.1\n","jupyter-client                   6.1.12\n","jupyter-console                  6.1.0\n","jupyter_core                     5.7.2\n","jupyter-server                   1.24.0\n","jupyterlab_pygments              0.3.0\n","jupyterlab_widgets               3.0.11\n","kaggle                           1.6.14\n","kagglehub                        0.2.7\n","keras                            2.15.0\n","keyring                          23.5.0\n","kiwisolver                       1.4.5\n","langchain                        0.2.10\n","langchain-community              0.2.9\n","langchain-core                   0.2.22\n","langchain-openai                 0.1.17\n","langchain-text-splitters         0.2.2\n","langcodes                        3.4.0\n","langgraph                        0.1.8\n","langsmith                        0.1.93\n","language_data                    1.2.0\n","launchpadlib                     1.10.16\n","lazr.restfulclient               0.14.4\n","lazr.uri                         1.0.6\n","lazy_loader                      0.4\n","libclang                         18.1.1\n","librosa                          0.10.2.post1\n","lightgbm                         4.1.0\n","linkify-it-py                    2.0.3\n","llvmlite                         0.41.1\n","locket                           1.0.0\n","logical-unification              0.4.6\n","lxml                             4.9.4\n","malloy                           2023.1067\n","marisa-trie                      1.2.0\n","Markdown                         3.6\n","markdown-it-py                   3.0.0\n","MarkupSafe                       2.1.5\n","marshmallow                      3.21.3\n","matplotlib                       3.7.1\n","matplotlib-inline                0.1.7\n","matplotlib-venn                  0.11.10\n","mdit-py-plugins                  0.4.1\n","mdurl                            0.1.2\n","miniKanren                       1.0.3\n","missingno                        0.5.2\n","mistune                          0.8.4\n","mizani                           0.9.3\n","mkl                              2023.2.0\n","ml-dtypes                        0.2.0\n","mlxtend                          0.22.0\n","more-itertools                   10.1.0\n","moviepy                          1.0.3\n","mpmath                           1.3.0\n","msgpack                          1.0.8\n","multidict                        6.0.5\n","multipledispatch                 1.0.0\n","multitasking                     0.0.11\n","murmurhash                       1.0.10\n","music21                          9.1.0\n","mypy-extensions                  1.0.0\n","natsort                          8.4.0\n","nbclassic                        1.1.0\n","nbclient                         0.10.0\n","nbconvert                        6.5.4\n","nbformat                         5.10.4\n","nest-asyncio                     1.6.0\n","networkx                         3.3\n","nibabel                          4.0.2\n","nltk                             3.8.1\n","notebook                         6.5.5\n","notebook_shim                    0.2.4\n","numba                            0.58.1\n","numexpr                          2.10.1\n","numpy                            1.25.2\n","nvtx                             0.2.10\n","oauth2client                     4.1.3\n","oauthlib                         3.2.2\n","openai                           1.36.1\n","opencv-contrib-python            4.8.0.76\n","opencv-python                    4.8.0.76\n","opencv-python-headless           4.10.0.84\n","openpyxl                         3.1.5\n","opt-einsum                       3.3.0\n","optax                            0.2.2\n","orbax-checkpoint                 0.4.4\n","orjson                           3.10.6\n","osqp                             0.6.2.post8\n","packaging                        24.1\n","pandas                           2.0.3\n","pandas-datareader                0.10.0\n","pandas-gbq                       0.19.2\n","pandas-stubs                     2.0.3.230814\n","pandocfilters                    1.5.1\n","panel                            1.3.8\n","param                            2.1.1\n","parso                            0.8.4\n","parsy                            2.1\n","partd                            1.4.2\n","pathlib                          1.0.1\n","patsy                            0.5.6\n","peewee                           3.17.6\n","pexpect                          4.9.0\n","pickleshare                      0.7.5\n","Pillow                           9.4.0\n","pip                              23.1.2\n","pip-tools                        6.13.0\n","platformdirs                     4.2.2\n","plotly                           5.15.0\n","plotnine                         0.12.4\n","pluggy                           1.5.0\n","polars                           0.20.2\n","pooch                            1.8.2\n","portpicker                       1.5.2\n","prefetch-generator               1.0.3\n","preshed                          3.0.9\n","prettytable                      3.10.2\n","proglog                          0.1.10\n","progressbar2                     4.2.0\n","prometheus_client                0.20.0\n","promise                          2.3\n","prompt_toolkit                   3.0.47\n","prophet                          1.1.5\n","proto-plus                       1.24.0\n","protobuf                         3.20.3\n","psutil                           5.9.5\n","psycopg2                         2.9.9\n","ptyprocess                       0.7.0\n","py-cpuinfo                       9.0.0\n","py4j                             0.10.9.7\n","pyarrow                          14.0.2\n","pyarrow-hotfix                   0.6\n","pyasn1                           0.6.0\n","pyasn1_modules                   0.4.0\n","pycocotools                      2.0.8\n","pycparser                        2.22\n","pydantic                         2.8.2\n","pydantic_core                    2.20.1\n","pydata-google-auth               1.8.2\n","pydot                            1.4.2\n","pydot-ng                         2.0.0\n","pydotplus                        2.0.2\n","PyDrive                          1.3.1\n","PyDrive2                         1.6.3\n","pyerfa                           2.0.1.4\n","pygame                           2.6.0\n","Pygments                         2.16.1\n","PyGObject                        3.42.1\n","PyJWT                            2.3.0\n","pymc                             5.10.4\n","pymystem3                        0.2.0\n","pynvjitlink-cu12                 0.3.0\n","PyOpenGL                         3.1.7\n","pyOpenSSL                        24.1.0\n","pyparsing                        3.1.2\n","pyperclip                        1.9.0\n","pyproj                           3.6.1\n","pyproject_hooks                  1.1.0\n","pyshp                            2.3.1\n","PySocks                          1.7.1\n","pytensor                         2.18.6\n","pytest                           7.4.4\n","python-apt                       2.4.0\n","python-box                       7.2.0\n","python-dateutil                  2.8.2\n","python-louvain                   0.16\n","python-slugify                   8.0.4\n","python-utils                     3.8.2\n","pytz                             2023.4\n","pyviz_comms                      3.0.2\n","PyWavelets                       1.6.0\n","PyYAML                           6.0.1\n","pyzmq                            24.0.1\n","qdldl                            0.1.7.post4\n","qudida                           0.0.4\n","ratelim                          0.1.6\n","referencing                      0.35.1\n","regex                            2024.5.15\n","requests                         2.31.0\n","requests-oauthlib                1.3.1\n","requirements-parser              0.9.0\n","rich                             13.7.1\n","rmm-cu12                         24.4.0\n","rpds-py                          0.19.0\n","rpy2                             3.4.2\n","rsa                              4.9\n","safetensors                      0.4.3\n","scikit-image                     0.19.3\n","scikit-learn                     1.2.2\n","scipy                            1.11.4\n","scooby                           0.10.0\n","scs                              3.2.6\n","seaborn                          0.13.1\n","SecretStorage                    3.3.1\n","Send2Trash                       1.8.3\n","sentencepiece                    0.1.99\n","setuptools                       67.7.2\n","shapely                          2.0.5\n","shellingham                      1.5.4\n","simple_parsing                   0.1.5\n","six                              1.16.0\n","sklearn-pandas                   2.2.0\n","smart-open                       7.0.4\n","sniffio                          1.3.1\n","snowballstemmer                  2.2.0\n","sortedcontainers                 2.4.0\n","soundfile                        0.12.1\n","soupsieve                        2.5\n","soxr                             0.3.7\n","spacy                            3.7.5\n","spacy-legacy                     3.0.12\n","spacy-loggers                    1.0.5\n","Sphinx                           5.0.2\n","sphinxcontrib-applehelp          1.0.8\n","sphinxcontrib-devhelp            1.0.6\n","sphinxcontrib-htmlhelp           2.0.5\n","sphinxcontrib-jsmath             1.0.1\n","sphinxcontrib-qthelp             1.0.7\n","sphinxcontrib-serializinghtml    1.1.10\n","SQLAlchemy                       2.0.31\n","sqlglot                          20.11.0\n","sqlparse                         0.5.1\n","srsly                            2.4.8\n","stanio                           0.5.1\n","statsmodels                      0.14.2\n","StrEnum                          0.4.15\n","sympy                            1.13.0\n","tables                           3.8.0\n","tabulate                         0.9.0\n","tbb                              2021.13.0\n","tblib                            3.0.0\n","tenacity                         8.5.0\n","tensorboard                      2.15.2\n","tensorboard-data-server          0.7.2\n","tensorflow                       2.15.0\n","tensorflow-datasets              4.9.6\n","tensorflow-estimator             2.15.0\n","tensorflow-gcs-config            2.15.0\n","tensorflow-hub                   0.16.1\n","tensorflow-io-gcs-filesystem     0.37.1\n","tensorflow-metadata              1.15.0\n","tensorflow-probability           0.23.0\n","tensorstore                      0.1.45\n","termcolor                        2.4.0\n","terminado                        0.18.1\n","text-unidecode                   1.3\n","textblob                         0.17.1\n","tf_keras                         2.15.1\n","tf-slim                          1.1.0\n","thinc                            8.2.5\n","threadpoolctl                    3.5.0\n","tifffile                         2024.7.2\n","tiktoken                         0.7.0\n","tinycss2                         1.3.0\n","tokenizers                       0.19.1\n","toml                             0.10.2\n","tomli                            2.0.1\n","toolz                            0.12.1\n","torch                            2.3.1+cu121\n","torchaudio                       2.3.1+cu121\n","torchsummary                     1.5.1\n","torchtext                        0.18.0\n","torchvision                      0.18.1+cu121\n","tornado                          6.3.3\n","tqdm                             4.66.4\n","traitlets                        5.7.1\n","traittypes                       0.2.1\n","transformers                     4.42.4\n","triton                           2.3.1\n","tweepy                           4.14.0\n","typer                            0.12.3\n","types-pytz                       2024.1.0.20240417\n","types-setuptools                 70.3.0.20240710\n","typing_extensions                4.12.2\n","typing-inspect                   0.9.0\n","tzdata                           2024.1\n","tzlocal                          5.2\n","uc-micro-py                      1.0.3\n","uritemplate                      4.1.1\n","urllib3                          2.0.7\n","vega-datasets                    0.9.0\n","wadllib                          1.3.6\n","wasabi                           1.1.3\n","wcwidth                          0.2.13\n","weasel                           0.4.1\n","webcolors                        24.6.0\n","webencodings                     0.5.1\n","websocket-client                 1.8.0\n","Werkzeug                         3.0.3\n","wheel                            0.43.0\n","widgetsnbextension               3.6.7\n","wordcloud                        1.9.3\n","wrapt                            1.14.1\n","xarray                           2023.7.0\n","xarray-einstats                  0.7.0\n","xgboost                          2.0.3\n","xlrd                             2.0.1\n","xyzservices                      2024.6.0\n","yarl                             1.9.4\n","yellowbrick                      1.5\n","yfinance                         0.2.40\n","zict                             3.0.0\n","zipp                             3.19.2\n"]}]},{"cell_type":"code","source":["import os\n","from google.colab import userdata\n","os.environ[\"OPENAI_API_KEY\"] = userdata.get('OPENAI_API_KEY')\n","os.environ[\"OPENAI_API_BASE\"] = userdata.get('OPENAI_API_BASE')\n","os.environ[\"LANGCHAIN_TRACING_V2\"] = \"true\"\n","os.environ[\"LANGCHAIN_API_KEY\"] = userdata.get('LANGCHAIN_API_KEY')\n","os.environ[\"LANGCHAIN_PROJECT\"] = \"LangGraph Tutorial\""],"metadata":{"id":"7KWKq6fbloq8"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["from typing import Annotated\n","\n","from langchain_openai import ChatOpenAI\n","from typing_extensions import TypedDict\n","\n","from langgraph.graph import StateGraph\n","from langgraph.graph.message import add_messages\n","\n","\n","class State(TypedDict):\n","    messages: Annotated[list, add_messages]\n","\n","\n","graph_builder = StateGraph(State)\n","\n","\n","llm = ChatOpenAI(model=\"gpt-4o-mini\", temperature=0)\n","\n","\n","def chatbot(state: State):\n","    return {\"messages\": [llm.invoke(state[\"messages\"])]}\n","\n","\n","# The first argument is the unique node name\n","# The second argument is the function or object that will be called whenever\n","# the node is used.\n","graph_builder.add_node(\"chatbot\", chatbot)\n","graph_builder.set_entry_point(\"chatbot\")\n","graph_builder.set_finish_point(\"chatbot\")\n","graph = graph_builder.compile()\n"],"metadata":{"id":"rNMA9hOylv2P"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["from IPython.display import Image, display\n","\n","try:\n","    display(Image(graph.get_graph().draw_mermaid_png()))\n","except Exception:\n","    # This requires some extra dependencies and is optional\n","    pass"],"metadata":{"id":"-4zvQtdqpqK3","colab":{"base_uri":"https://localhost:8080/","height":236},"executionInfo":{"status":"ok","timestamp":1721568211129,"user_tz":-480,"elapsed":1728,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"41b5aef3-9d79-48d8-e366-57326f8821e0"},"execution_count":null,"outputs":[{"output_type":"display_data","data":{"image/jpeg":"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\n","text/plain":["<IPython.core.display.Image object>"]},"metadata":{}}]},{"cell_type":"code","source":["while True:\n","    user_input = input(\"User: \")\n","    if user_input.lower() in [\"quit\", \"exit\", \"q\"]:\n","        print(\"Goodbye!\")\n","        break\n","    for event in graph.stream({\"messages\": (\"user\", user_input)}):\n","        for value in event.values():\n","            print(\"Assistant:\", value[\"messages\"][-1].content)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"0f6ZRlnPVIp5","executionInfo":{"status":"ok","timestamp":1721568372161,"user_tz":-480,"elapsed":94337,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"8002c4ce-7080-4d9c-a05b-2b0487a97b10"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["User: 你好\n","Assistant: 你好！有什么我可以帮助你的吗？\n","User: 你是谁\n","Assistant: 我是一个人工智能助手，旨在回答你的问题和提供信息。有什么我可以帮你的吗？\n","User: 我是小灰\n","Assistant: 你好，小灰！很高兴见到你。有任何我可以帮助你的吗？\n","User: 我是谁\n","Assistant: 你是提问者，我在这里回答你的问题。如果你愿意分享更多关于你的信息，我可以更好地帮助你！\n","User: q\n","Goodbye!\n"]}]},{"cell_type":"markdown","source":["# Part 2: 集成工具的聊天机器人"],"metadata":{"id":"o1HOn0QMjIi3"}},{"cell_type":"code","source":["os.environ[\"TAVILY_API_KEY\"] = userdata.get('TAVILY_API_KEY')"],"metadata":{"id":"-U7OKL3uWXJD"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["from langchain_community.tools.tavily_search import TavilySearchResults\n","\n","tool = TavilySearchResults(max_results=2)\n","tools = [tool]\n","tool.invoke(\"What's a 'node' in LangGraph?\")"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"5HFWUWR-WZ9x","executionInfo":{"status":"ok","timestamp":1722150039036,"user_tz":-480,"elapsed":2785,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"ba1c4d50-0ae9-46fe-f06b-ccfab34a7547"},"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":["[{'url': 'https://cobusgreyling.medium.com/langgraph-from-langchain-explained-in-simple-terms-f7cd0c12cdbf',\n","  'content': 'LangGraph. Again considering the image blow, a snippet of LangGraph Python code is shown on the left, with the graph drawn out on the right. You can see in the code where the node is defined, builder.add_node with a ReturnNodeValue.For each node having an edge defined builder.add_edge.. You also see that a is set as the entry_point and d as the finish_point.'},\n"," {'url': 'https://www.datacamp.com/tutorial/langgraph-tutorial',\n","  'content': 'LangGraph is a library within the LangChain ecosystem that provides a framework for defining, coordinating, and executing multiple LLM agents (or chains) in a structured and efficient manner.'}]"]},"metadata":{},"execution_count":4}]},{"cell_type":"code","source":["\n","class State(TypedDict):\n","    messages: Annotated[list, add_messages]\n","\n","graph_builder = StateGraph(State)\n","\n","llm = ChatOpenAI(model=\"gpt-4o-mini\", temperature=0)\n","# Modification: tell the LLM which tools it can call\n","llm_with_tools = llm.bind_tools(tools)\n","\n","def chatbot(state: State):\n","    return {\"messages\": [llm_with_tools.invoke(state[\"messages\"])]}\n","\n","graph_builder.add_node(\"chatbot\", chatbot)"],"metadata":{"id":"xVeFXQnxWmox"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["import json\n","from langchain_core.messages import ToolMessage\n","\n","class BasicToolNode:\n","    \"\"\"A node that runs the tools requested in the last AIMessage.\"\"\"\n","\n","    def __init__(self, tools: list) -> None:\n","        self.tools_by_name = {tool.name: tool for tool in tools}\n","\n","    def __call__(self, inputs: dict):\n","        if messages := inputs.get(\"messages\", []):\n","            message = messages[-1]\n","        else:\n","            raise ValueError(\"No message found in input\")\n","        outputs = []\n","        for tool_call in message.tool_calls:\n","            tool_result = self.tools_by_name[tool_call[\"name\"]].invoke(\n","                tool_call[\"args\"]\n","            )\n","            outputs.append(\n","                ToolMessage(\n","                    content=json.dumps(tool_result),\n","                    name=tool_call[\"name\"],\n","                    tool_call_id=tool_call[\"id\"],\n","                )\n","            )\n","        return {\"messages\": outputs}\n","\n","tool_node = BasicToolNode(tools=[tool])\n","graph_builder.add_node(\"tools\", tool_node)"],"metadata":{"id":"ujQ8l7e7W227"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["from typing import Literal\n","\n","\n","def route_tools(\n","    state: State,\n",") -> Literal[\"tools\", \"__end__\"]:\n","    \"\"\"Use in the conditional_edge to route to the ToolNode if the last message\n","\n","    has tool calls. Otherwise, route to the end.\"\"\"\n","    if isinstance(state, list):\n","        ai_message = state[-1]\n","    elif messages := state.get(\"messages\", []):\n","        ai_message = messages[-1]\n","    else:\n","        raise ValueError(f\"No messages found in input state to tool_edge: {state}\")\n","    if hasattr(ai_message, \"tool_calls\") and len(ai_message.tool_calls) > 0:\n","        return \"tools\"\n","    return \"__end__\"\n","\n","# The `tools_condition` function returns \"tools\" if the chatbot asks to use a tool, and \"__end__\" if\n","# it is fine directly responding. This conditional routing defines the main agent loop.\n","graph_builder.add_conditional_edges(\n","    \"chatbot\",\n","    route_tools,\n","    # The following dictionary lets you tell the graph to interpret the condition's outputs as a specific node\n","    # It defaults to the identity function, but if you\n","    # want to use a node named something else apart from \"tools\",\n","    # You can update the value of the dictionary to something else\n","    # e.g., \"tools\": \"my_tools\"\n","    {\"tools\": \"tools\", \"__end__\": \"__end__\"},\n",")\n","# Any time a tool is called, we return to the chatbot to decide the next step\n","graph_builder.add_edge(\"tools\", \"chatbot\")\n","graph_builder.set_entry_point(\"chatbot\")\n","graph = graph_builder.compile()"],"metadata":{"id":"C072InU4XAP9"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["from IPython.display import Image, display\n","\n","try:\n","    display(Image(graph.get_graph().draw_mermaid_png()))\n","except Exception:\n","    # This requires some extra dependencies and is optional\n","    pass"],"metadata":{"colab":{"base_uri":"https://localhost:8080/","height":236},"id":"H2bAeKfUXSuL","executionInfo":{"status":"ok","timestamp":1721569497617,"user_tz":-480,"elapsed":1345,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"33657a86-a13c-4a96-9a6d-516338312dc9"},"execution_count":null,"outputs":[{"output_type":"display_data","data":{"image/jpeg":"/9j/4AAQSkZJRgABAQAAAQABAAD/4gHYSUNDX1BST0ZJTEUAAQEAAAHIAAAAAAQwAABtbnRyUkdCIFhZWiAH4AABAAEAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAACRyWFlaAAABFAAAABRnWFlaAAABKAAAABRiWFlaAAABPAAAABR3dHB0AAABUAAAABRyVFJDAAABZAAAAChnVFJDAAABZAAAAChiVFJDAAABZAAAAChjcHJ0AAABjAAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAAgAAAAcAHMAUgBHAEJYWVogAAAAAAAAb6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UAABjaWFlaIAAAAAAAACSgAAAPhAAAts9YWVogAAAAAAAA9tYAAQAAAADTLXBhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABtbHVjAAAAAAAAAAEAAAAMZW5VUwAAACAAAAAcAEcAbwBvAGcAbABlACAASQBuAGMALgAgADIAMAAxADb/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/wAARCADbAMcDASIAAhEBAxEB/8QAHQABAAEFAQEBAAAAAAAAAAAAAAYDBAUHCAEJAv/EAFcQAAEDBAADAgcICg0KBwAAAAECAwQABQYRBxIhEzEIFBYiQVGUFyMyVVZh0dMVQnF0dYGRk5XSCSQ0NjhSU1SSsbK01Bg1N2JjcoKhs8EzRVeDhMPx/8QAGgEBAQADAQEAAAAAAAAAAAAAAAECAwQFB//EADMRAQABAwAFCgQHAQAAAAAAAAABAgMRBBIhMVETFEFSYXGRobHBFSMz0QUiQlOB4fAy/9oADAMBAAIRAxEAPwD6p0pSgUpSgUq0ulzj2a3vzZSilhlPMeVJUpR7glKR1UonQCR1JIA6msH5PS8m9/vzjrMVWy3Z47pQhCfR2yknbi/WAeQb0ArXOrbTRExrVTiP9uXDMyb7bYThRIuEVhY6FLr6UkfiJqj5VWX44ge0o+mqUfC8fiNhDFitrSAANIiNju6D0VV8lbL8TwPZkfRWfye3yNh5VWX44ge0o+mnlVZfjiB7Sj6aeStl+J4HsyPop5K2X4ngezI+inye3yXYeVVl+OIHtKPpp5VWX44ge0o+mnkrZfieB7Mj6KeStl+J4HsyPop8nt8jYeVVl+OIHtKPpr1GTWdxQSi7QVKPoTJQT/XXnkrZfieB7Mj6K8XidjcQUqs1vUk9CDFQQf8AlT5Pb5GxlEqC0hSSFJI2CDsEV7UYXgUGCtT9gUrHZZPN+0hqOs/7Rj4CgfSQArv0oE7rI2O8uT1vw5jHilzi6DzIO0LB7nGz6UK0dHvBBB6isaqIxrUTmPCUxwZalKVpQpSlApSlApSlApSlApSlApSlBF7tq7ZxabcvSo0FhdycQftneYNs/dA26rr6Qg942JRUYdHifElhxewifa1NIVrpzMu82t+sh4kf7p9VSeui7uoiN2PvnzWSlKVzogELjxg9yyi5Y7DvDky7W5T6JDUaBJcQHGUlTraXUtlC3EgHaEqKtjWt9KjPCnwnsb4h8M5mYXBqXYGIBWqah+BK7NpHbuNNcjimUh5RCBsN8xSVaIB6VEcOF4xzwgDBwuyZbbMVuVzuEjJoN8txRam3OVSkzIUhXpddCT2aFKBCySlBFRzF7nnWHeDvcMIs+O5PasssU91MuZGtaldpCcualOuwHFAtvu+LuFSUjZ2D02BQbytXhBYDecQyDJ4t+3aMfSV3VTsOQ0/DTy821sLbDo2Oo8zro63qopnfhY4pjFpsdxtbc++Q7je41qVJZtc3sg24dreaUGCH9J6pDZPOT5pOtVo27YbeJdl4+ps2N53Jh5DiERFreyNiVIlz3mTIS4kdpzOJVt1PK0oJVrZSnl61vbj9Ybinh7g8202WZdE41kNpusm3W1guSfFmFgOBpodVqSDvlHXoaDb9nu0e+2mHconbeKy2UvteMMLYc5VDY5m3AlaDo9UqAI7iBV5WNxy+N5LZIlzaiTYDclPOmPcoy40hA2RpbawFJPTeiPSKyVAqMZdq13Ow3lGkrbmIgPHr57MhQbCfzpZV+I+upPUYzxPjcWz29IJdl3WIUgDfRl0SFE+ocrKuvziuix9SInd093T5LG9J6UpXOhSlKBSlKBSlKBSlKBSlKBSlKDFZFZlXiI0WHEsXCI6JMN9YJDboBHUAglKkqUhQB6pWoAjvqna75Gvgft8poRrihJTJtzx2eXuKk7A52zvosDR7jogpGZrHXnHrdkLTbdwiNyeyJU04dpcaURoqQsaUg66bSQa3U1UzGrXu9P8Af7tvehA8GzhOkgjhviwI7iLQx+rXn+TXwn/9NsV/RDH6tSE4MW+kfIr7HR0AR44HdD7riVKP4zunkTI+VV+/PM/VVlqW+v5SYjikkeO1EjtMMtpaZaSEIbQNJSkDQAHoAFVKi/kTI+VV+/PM/VU8iZHyqv355n6qnJ2+v5SYjilFK598Fq9ZDxj4L2nKr9lF1Rc5UmW04Iamm2+VqS42nQLZPwUDfXvrbXkTI+VV+/PM/VU5O31/KTEcVhkXA7h5l15kXa94RYLvdJPL20ybbmnXXOVISnmUpJJ0lIH3AKx6vBv4UrSgK4cYuoIHKkG0sHlGydDzfWSfx1n/ACJkfKq/fnmfqqDCXiCFZPflpPTXbtD/AJhsGnJ2+v5SYjirWy04vwtx0RbdCt2NWZtZUmPEaSw12ij3JQkDalH0AbJ7tmvbPCkXW7C+z2DGKWlMwYq/htNqIKlrHoWrlT0+1AA7yqqlrwu1WqaJoadmXAAgTJz65Dqd94SpZPID6k6HzVnak1U0RMW+np+xsjcUpStCFKUoFKUoFKUoFKUoFKUoFKUoFKUoFKUoFKUoOd/AD/gw499+3H++vV0RXO/gB/wYce+/bj/fXq6IoFKUoFKUoFKUoFKUoFKUoFKUoFKUoFKUoFKUoFKUoFKUoFKUoOd/AD/gw499+3H++vV0RXO/gB/wYce+/bj/AH16uiKBSlKBSlKBSlKBSlKBSlKBSlKBSlKBSlKBSlKBSlWN6vEew25yZJ51IQUpS22nmW4tRCUoSPSSSAPu+irETVMRG8X1KhJyHLnTzt2qzsIPUNuznVLA+chrW/ubHzmvPs7mH8wsftb31ddfNa+MeMLhN64b/ZP+Baspwm2cSbZHLlxsAEO48g2VQlrJQr/23FHu9Dqieia6t+zuYfzCx+1vfV1j8hTkWVWG42W6Wewy7bcI7kSTHXLe040tJSpJ979IJpzWvjHjBh8x/wBjy4KOcU+O8K9yW1CyYkpu6vuDYCpIVuM3sdx508/qIaUPTX1/rnXwdODF08HDBXccszFpuCpEtyZJnyJDiXHlK0EggN6ASgJTodN7PTmNbT+zuYfzCx+1vfV05rXxjxgwm9KhH2dzD+YWP2t76uvRfcw2NwLJr06lvfV05rXxjxgwm1KwWO5Iu6vPQp0VMC6sIS44whztG1oUSAttek8w2CDsAgjqNFJOdrmroqtzq1b0KUpWAUpSgUpSgUpSgUpSgUpSgUpSgVEOJJ/aVkHoN3jbH/ETUvqIcSf3HY/wvG/rNdWjfWpZU715Vpd7xAx+2yLjdJsa22+MguPy5bqWmmk+lSlqICR85NQ7jnxBl8LeFV+yWBHalXCKhpqK3IJDXbOvIZbK9deUKcSTr0A9RWq+O+KZfj3g58SXclzlzLEu2RY7BdrjxUMu7Gy2WgDy+gJXzH/WrfM4YukAQQCDsGlaIiZdlPDjiMux5ZmbF2ss7GJl78fetrUYWtyMtoOFIR8Jrld5tLKlDk+Ed1GuFvEvN7txEgY5cb5fZlmyaxTJltvF3scO3vNOtFrlejtoKttlLwPK+jewn4QJFTWHR1zvttstuXcLhcIsCAhSUKlSX0ttJUpYQkFSiACVkJA9JIHfV9XE1osl1h+AMw+7kUqeiaq1mJHkx2A3AIurQPJyISpYJIJ7RSj06EdannETi9nHg93LIIN4vTWdNPY6/eLVIkwWorsaS080yWnQyEpUyS+hXNoK80jfpqa/TI6dr8tuIdTzIUladkbSdjYOjWjY9wzzCOI2M4jf82VkTeX22eluai2x471rmMNoX2jISjlW2QtWkupUQUp2SCQfz4FtnuFv4CY1KmX6XdY0uKFR4chlhCIQDjgUlCm0JUoKJBPOVHp011qxVmcDcEEkcTYQHcbPJJ+fTzGv6zU5qCwv9J0H8Dyv+vHqdVhpW+nu95WegpSlcSFKUoFKUoFKUoFKUoFKUoFKUoFRDiT+47H+F439ZqX1g8wsj18tLaYpR43GkNS2UuHSVqQoHlJ0dcw2nejre+uq6NHqim7TMrG9gcuxO1Z1jNyx+9xEzrVcGVMSGFEjmSfUR1BB0QR1BAIrXrvg6wrhiN9xy7ZpmF9tt2gG3KTcri26qO1sHbfvQBX0A51hatempheOI1uxq2yp97h3WzRIjZdlPyre6WmEgecVOoSpvQ9YUR89UrFxSseUWmNdbMi6XW2SU87EyFapLzLo2RtK0tkEbBHQ+iu/ka5/SurKhlnCKw5tfkXO7eMyNWaZYnIgcCWXY0kt9rzdObm97ABChrZ6d2sFi3g/WzGMosGQLybJrzcrIw7DiKuk1txAjLQElkoS2kco0hXMAFkoTzKUBqpn5Zxviy/foSX9VTyzjD/yy/foSX9VTkK+rJqzwQBrwZcfawy74iL7kZxie8081azNR2cDkkpkhMdXZ86EladdVKIB0CDoi+tng8442b87fp94zOXebeq0yJeQSkuuIhqOyw12aEJQkq0okDmJAO9gVIMf4r4/llrbudjNxvNtdKkomW+2SX2VlKilQC0NkEhQIPXoQRWR8s43xZfv0JL+qpyFfVNWeCL4TwNteHZIxfpF8v8AlF0iRFQID9/mJf8AEWFEFaWglCBtXKkFauZZCQCqshwz4TwOFLE2HaLtd5FodWVxrVOkIdjwAVqWUMaQFBJKz0UpXcNVmPLON8WX79CS/qqw2TcZsWwtiM9kEmZYmZLwjsO3K3SI6XXD3ISVoAKj6qchXH6ZNWeCQwv9J0H8Dyv+vHqdVEMYt8q4X5d9kxXIDKYpiRmJAAdUFKSpa1J+12UpAB69CTrdS+uPSZiaoiOiEkpSlciFKUoFKUoFKUoFKUoFKUoFKV+VrS2hSlKCUpGyonQAoP1UK4scUofCTHI91lWi8X1yVMagRoFkhqkyHXnN8o0OgHQ9SR6ANkgG3unEK9HPcStNgxV6/wCM3eM5MmZSxLbESI0E+9hPUlxS1FBGteadp5tK5a/CrhXC4T2i5Qot3vF8duM924yZt6mKkvLcXoaBPQAJSkdB11s7NBQgYDe3+IuSXy85U/eMVucFEGJiT0RsRY6dDtVObG3FKPMOuvNWQebSdTlhhuMy2yy2lpptIQhtCQlKUgaAAHcBVSlArnHw8OOfuLcDZ7UCR2OR5FzWy38p0ttKh788PSOVB0CO5S0Gujq0N4QfgcYh4SeSW285PfMkhuW+J4oxEtcphthI51LUvlcZWedXMASCNhCenSg5N/Yu+Ov2HyO6cL7pICYl05rjai4r4MlKR2rQ/wB9tIUB3DslelVfSuvn14E/gYYZk+IYbxUkXjIo+RQbs7JbjxpTCYqjGlrShKklkrKVBsBQ5xvata3X0FoFUZUNic12UlhuQ3zJXyOoChzJIUk6PpBAIPoIFVqUGu5WI3/EMmzLMrXe7zk4nW/mi4ZJfaTFTLbQAnsHFAdkFhKUkb1tSlHmOtZnCM7GT43YZt4tj+I3m6trUmw3dxCZaVoJ50hIPnga5tjrylJITvQldRXMuFuK8QLrj9zyCyx7lcbBLTNtkpzYcjOgpO0kEbBKUkpOweUbHQUEqpWqnctyrhUxxByPiHPt9wwqC6mZaHbPCdM1mOokKaebGwrk8zShve1KJA6J2HjeRW7Lsft17tEjxu13GOiVFkBCkdo0tIUlWlAEbBB6gUGSpSlApSlApSlApSlApSlBiMqy6y4PZHbxkFzjWe1tLbbcmS3AhtClrShG1HoNqUkb+eoZcMfyTiTc85xfM7JbY/DqXGRCgLhznfHpnMnbq1lPKG09QkJ6EFB+Ekg1I+J1jtGRYBfYV+sqcjtXiyn3rUob8a7L31KB1HUqQnXz6rzhhmTfEHh7YMjatsizt3GIh8QJaSHY+xooVsDuI1vXXvoMrjOM2vDcft9jskJq3WmAyliNFZGktoHcB6T909SeprJ0pQKUpQKoy5bECK9KlPNxozCFOOvPLCUNoA2VKJ6AAAkk1j8qyuz4Pj06+364sWq0QWy7IlyVcqEJ/wC5J0AB1JIABJrmJiDk/huz25Vybn4jwJZcC2IBJZnZOQdhbmurcbYBAHVXeNnRQEp8ABQX4L2OLSQpKplxKVA7BHjr3UV0VVlZbJb8btMS12qExbrbEbSzHixmwhtpAGglKR0Aq9oFKUoFKUoPCNjR6ioZfOGpuufYzk8TI7xaE2ZpyO5aIcjUGaypJ0l1ojW0q5SFDrpOvURNKUEJ4d5tfsjRdmsqxVzDpsW4uxIqH5jT7c5kec260pJ2dpKdgjodjrogTatU8X4uEv5/wtXlEybGvTV4cVYG4oJbek9keZLuknSeX1kdfTW1qBSlKBSlKBSlKBSlflbiGxtagkf6x1Qak8Ibwl8e8Gq2We45LZb/AHKBc3XGESbNFbdbZcSEqCHVOOICVLBUUgbJDa/4tcVwv2TnPLlMXYcexy23a6Tr6tu2XC8pKdw3FlLDC47Kk6dG0bWHVDvGj0VX0H4kYJjnFfC7pi2RstTbVcGi24kqHM2r7VxBPwVpOiD6CK+aHCPwULzwx8OLFMYvTfjdlgyl3qHdkp96kx2EqcaX39FdoltKkk7ST6QQTcSPqzSqXjTP8s3/AEhTxpn+Wb/pCmJFWofxV4sYzwYw6XkuVXFMC3seahA852Q4R5rTSO9azru+6SQASMFxx4+49wMxpidcEu3a8XBzxa0WK3jnlXGR0AbbSN6G1J2rXTY6ElKTrnhVwEyLPcwicUuNamZ+TNefZMWbPNAsCCdjzeoW/wB21HeiAdkhJTBicV4XZT4UuQwc44twHLLg8RwSMf4fOKPvn8WTPH2yiD0bPdvRAHMF9TttoZbQ22hKG0AJSlI0AB3ACv1SgUpSgUpSgUpX4W6hvXOtKd93MdUH7q0uz8uLapr1vionT22VrjxXXuxS84EkpQV8quQE6HNo63vR7qreNM/yzf8ASFPGmf5Zv+kKuJHzoyD9lJQ5eIouXBeL4/apCykTrwFvRnRtKuQmKC2vvBPf6K698F3j3J8I7hs9lz+MLxVr7IOw2I65njQfQhCCXUr7NvpzKWjWj1bPX0Dhvw6PBbnveEbYpuJx0uRc/lBshA97jz9gPKWQPNSpJDpJ/wBqe5NfRnhrhVm4W4FYsTs6m0W+0xURmzsAuEdVOK19stRUo/Oo0xIlVKpeNM/yzf8ASFeiQ0ogB1BJ7gFCmJFSlKVApSlBa3Sb9jbZLl8vN2DK3eX18qSf+1a8teJWq/W6Jcrzb4l4uUplDz0mcwl5W1AEpTzDzUDuCRoaHr2anOVfvYvH3m9/YNR7Gv3uWr70a/sCvS0eZotzVTOJyy3Qsvc+xb5NWf2Br9WnufYt8mrP7A1+rUF4V+EVYuJIykuNSbMixzJiFvTYclljxVhYT2y3nWkIQo75i0TzoG9joTUgwjjbhXEWe/CsN7EqW1H8bLL8Z6MpbG9ds32qE9o3sgc6Np6jr1FbYv3J/XPimZ4s17n2LfJqz+wNfq09z7Fvk1Z/YGv1awGJceMEzq/os1kyBubPdS4uOkx3mm5SW/hlh1aAh4J9JbUrp17qjWD+EPa18HsTy7Npce1zr4XG241uivvF1xK3BpplAccOko2e/XedU5xc68+JmeLYZ4fYz0Ldgt0dwdUvRoyGXEH1pWgBST84IIqRYJdJF0sBMp0yJEaTIhqeOtuBp1SEqOgBzFKQToAb3rpVhZLzDyOzwrrbnvGIE1lEhh7lKedtQ2lWlAEbBHeK/XDP/Mlw/C07+8LrC9VNyzM1TnEx7rnMbUupSleWxKUpQKtbpdItlt8idNeTHiMIK3HFdwA+YdSfUB1J6CrqtQcdby47Os1jQrTBSudITv4RSQlofONlavuoTXZoejzpV+m1x9FhHMq4i3nLH3EsyJFntWyG4sdfZvOJ9BccT5wJ/ipIA3o82t1DVWG2uLUtyBHdcVrmW60FqV90nqavqV9Hs2qNHp1LUYhjrSx/k9aviyH7Oj6KeT1q+LIfs6PorIVELzxcxLH7y5a594QxKaUlDx7FxTTCla5UuupSUNk7HRSh3itlV2KIzVVj+TM8Wf8AJ61fFkP2dH0U8nrV8WQ/Z0fRUdvnGHEccuc633C7FmXAUgS0IivOCOFIStKnFJQQlBStPnkhPeN7BAu8o4mY1hz8Nm63RLL8tBdZaZacfWpsd7nK2lRCP9Y6Hz1jy9EZ/Pu37TM8WX8nrV8WQ/Z0fRQ47aiCPsZD0en7nR9FYLhPl0vPOHdkv85thqVOZLjiIySlsHmUPNBJPcB3k1Layoua9MVROyTM8VeyXG4Yu4ldmnv28JI94SoqYUPUWj5v4wAfURW8eH2fM5nDW28hMW7RwPGIyTtJB6BxBPek6+6D0PoJ0PV3Y7w5jeS2m6tq5Q1IQy91+Ew4oIcB9ethWvWgV5Wn6DRpVuaoj88bp9pWJzsl03SlK+ejF5V+9i8feb39g1Hsa/e5avvRr+wKkmRsrkY9dGm0lTi4rqUpHpJQQKjWLrS5jVpUk7SqIyQfWOQV6Fn6M9/svQ5mumJ5FeOH3Grhq1j93Yvd3u90u1umLiLTb5jLrqXm0CT8AKWNtlJIIO96FZDLrfe/CBym0/YTGL5h8a1Y3eYUiZfYKoPK/MjJZajtA9XAhQ5ypIKByJ0STXTlKaqOYceRe83d4LY5Hwq+YzIwyQzKvE25QTHjR0sQ3I6mGHT5rwcUsaLZI5Rs6rDY/YFWngfh9rv2NZ1Z8rxW4zI0O645a1SJEN/az2yEjmD0d1DoSTyqSrqDrWx1vSmqIjwkuOTXbhrjszMoiYOTvREKnsJSE8rnzpBISojRKR3EkeipHwz/AMyXD8LTv7wururbhqgpsMxf2rl0nKSdd48ZcG/+R/8Aysq9lirvj3XoSylKV5qFKUoFaQ43RVR81tUpX/hyoC2UnX2zbnMR+R0fkPqrd9RniBhyc0sJioWlmcwsPxHl70hwAjStfaqBKT8x33gV6X4fpFOjaTTXXu3T/Kw5/pSXGcjyJFvnxlR5TW0PxXh1Ho/4kn0EdCKho4MYEDsYbYwfwe1+rX0KaqpiJoxMd/8AUsEyrnKJhbNuumUWHJ7Hmdy+yl3kvtO2eXL+x8uNIXsFwNuJbQQFELCwOifTW2vcXwH5GWL9Htfq1MWWUR2kNNIS22hISlCRoJA6ACtFdmb2NeIjH8+sDTj2LzWPdrjtW2UWJkFlmCCytXjITbUt6bJHvh5hy9N9enfVhiarnw8yxm53PHbzdI92x22RWX4EJT7kR1hCg4w4kdW+YrCtnQ2Ds9Om9KVObRmKonExmfGZn3EA4CW2ZaOEGMw58R+BMajqDkaS2W3Gz2ijpST1B61P6jt+4dYtlE7x28Y7bLpL5A328uKhxfKO4bI3rqax3uLYD8jLF+j2v1a2UU126YopiJiNm/8AoTOqT8VVxciQW+rsuUzHQNb6qcSN/iGz+KsdYsZsmGwnmbRbYVmiLX2riIrSWUFWgOY6AG9ADfzVt3hLgj789jJLiypllpKvEI7iSFkqHKXlA93m7CR6lKPpFa9J0mNFszcr39HetO/Lb9KUr5mpUTlcPk9u4u2Xu5WNlaisxYYYWyFHqSlLrS+XZ66SQNknXWpZStlFyq3/AMyucIb5AXD5Z3v8xC/w9PIC4fLO9/mIX+HqZUrdzm52eEfYyhvkBcPlne/zEL/D08gLh8s73+Yhf4eplSnObnZ4R9jKII4fyF+bKyq9SmT8Jr9rM8w9I52mUrH3UqB9RFSmHDYt0RmLFZRHjMoDbbTSQlKEgaAAHcKrUrXXdrubKp9vQzkpSlaUKUpQKUpQYXJMNs2XNIRdYKJC2wQ28CUOt77+VxJCk/iPWoU9wDtalks329R0HuQFsLA+4VNE/lJrZ9K7LWmaRYjVt1zELlqz3AYPylvf5Iv1FPcBg/KW9/ki/UVtOlb/AInpf7np9jLVnuAwflLe/wAkX6inuAwflLe/yRfqK2nSnxPS/wBz0+xlqz3AYPylvf5Iv1FejgDA31yS9kf/ABR/9FbSpT4npf7noZQqwcIMcsMhuSph66S2yFIeuLna8pHcQjQQD84SDU1pSuK7euXqta5VMz2mSlKVpR//2Q==\n","text/plain":["<IPython.core.display.Image object>"]},"metadata":{}}]},{"cell_type":"code","source":["from langchain_core.messages import BaseMessage\n","\n","while True:\n","    user_input = input(\"User: \")\n","    if user_input.lower() in [\"quit\", \"exit\", \"q\"]:\n","        print(\"Goodbye!\")\n","        break\n","    for event in graph.stream({\"messages\": [(\"user\", user_input)]}):\n","        for value in event.values():\n","            if isinstance(value[\"messages\"][-1], BaseMessage):\n","                print(\"Assistant:\", value[\"messages\"][-1].content)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"IqYozQmRXX0n","executionInfo":{"status":"ok","timestamp":1721569646745,"user_tz":-480,"elapsed":70823,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"0661dd36-22c5-46ed-89f7-8f7eb748e3bd"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["User: hi\n","Assistant: Hello! How can I assist you today?\n","User: what's langgraph all about?\n","Assistant: \n","Assistant: [{\"url\": \"https://www.langchain.com/langgraph\", \"content\": \"LangGraph is a stateful, orchestration framework that brings added control to agent workflows. LangGraph Cloud is a service for deploying and scaling LangGraph applications, with a built-in Studio for prototyping, debugging, and sharing LangGraph applications.\"}, {\"url\": \"https://langchain-ai.github.io/langgraph/\", \"content\": \"Additionally, LangGraph includes built-in persistence, enabling advanced human-in-the-loop and memory features. LangGraph is inspired by Pregel and Apache Beam. The public interface draws inspiration from NetworkX. LangGraph is built by LangChain Inc, the creators of LangChain, but can be used without LangChain. Key Features\\u00b6\"}]\n","Assistant: LangGraph is a stateful orchestration framework designed to enhance control over agent workflows. It allows for advanced features like built-in persistence, which supports human-in-the-loop scenarios and memory capabilities. The framework draws inspiration from systems like Pregel and Apache Beam, and it offers a public interface similar to NetworkX.\n","\n","LangGraph also includes LangGraph Cloud, a service for deploying and scaling applications, complemented by a Studio for prototyping, debugging, and sharing. While it is developed by LangChain Inc., it can be utilized independently of LangChain.\n","\n","For more information, you can visit the following links:\n","- [LangChain](https://www.langchain.com/langgraph)\n","- [LangGraph Documentation](https://langchain-ai.github.io/langgraph/)\n","User: q\n","Goodbye!\n"]}]},{"cell_type":"markdown","source":["# Part 3: 为聊天机器人添加记忆"],"metadata":{"id":"pcdMpZPHkqgP"}},{"cell_type":"code","source":["from langgraph.checkpoint.sqlite import SqliteSaver\n","\n","memory = SqliteSaver.from_conn_string(\":memory:\")"],"metadata":{"id":"rPrP45gJYWPS"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["from typing import Annotated\n","\n","from langchain_community.tools.tavily_search import TavilySearchResults\n","from langchain_core.messages import BaseMessage\n","from typing_extensions import TypedDict\n","from langchain_openai import ChatOpenAI\n","from langgraph.graph import StateGraph\n","from langgraph.graph.message import add_messages\n","from langgraph.prebuilt import ToolNode, tools_condition\n","\n","\n","class State(TypedDict):\n","    messages: Annotated[list, add_messages]\n","\n","graph_builder = StateGraph(State)\n","\n","\n","tool = TavilySearchResults(max_results=2)\n","tools = [tool]\n","llm = ChatOpenAI(model=\"gpt-4o-mini\", temperature=0)\n","llm_with_tools = llm.bind_tools(tools)\n","\n","\n","def chatbot(state: State):\n","    return {\"messages\": [llm_with_tools.invoke(state[\"messages\"])]}\n","\n","\n","graph_builder.add_node(\"chatbot\", chatbot)\n","\n","tool_node = ToolNode(tools=[tool])\n","graph_builder.add_node(\"tools\", tool_node)\n","\n","graph_builder.add_conditional_edges(\n","    \"chatbot\",\n","    tools_condition,\n",")\n","# Any time a tool is called, we return to the chatbot to decide the next step\n","graph_builder.add_edge(\"tools\", \"chatbot\")\n","graph_builder.set_entry_point(\"chatbot\")"],"metadata":{"id":"g950zYXjYcOp"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["graph = graph_builder.compile(checkpointer=memory)"],"metadata":{"id":"qQqQh10XYk2o"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["from IPython.display import Image, display\n","\n","try:\n","    display(Image(graph.get_graph().draw_mermaid_png()))\n","except Exception:\n","    # This requires some extra dependencies and is optional\n","    pass"],"metadata":{"colab":{"base_uri":"https://localhost:8080/","height":236},"id":"KwsGU-2GYtAN","executionInfo":{"status":"ok","timestamp":1721570406619,"user_tz":-480,"elapsed":607,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"9ee48d3f-2cf5-4958-dee8-4c98e323c2cd"},"execution_count":null,"outputs":[{"output_type":"display_data","data":{"image/jpeg":"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\n","text/plain":["<IPython.core.display.Image object>"]},"metadata":{}}]},{"cell_type":"code","source":["config = {\"configurable\": {\"thread_id\": \"1\"}}"],"metadata":{"id":"FCJzv2D2YwIv"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["user_input = \"Hi there! My name is Will.\"\n","\n","# The config is the **second positional argument** to stream() or invoke()!\n","events = graph.stream(\n","    {\"messages\": [(\"user\", user_input)]}, config, stream_mode=\"values\"\n",")\n","for event in events:\n","    event[\"messages\"][-1].pretty_print()"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"o7SbKd7lYyql","executionInfo":{"status":"ok","timestamp":1721570490833,"user_tz":-480,"elapsed":1996,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"bf4abd7d-72cf-4883-9453-08a76e253c01"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["================================\u001b[1m Human Message \u001b[0m=================================\n","\n","Hi there! My name is Will.\n","==================================\u001b[1m Ai Message \u001b[0m==================================\n","\n","Hi Will! How can I assist you today?\n"]}]},{"cell_type":"code","source":["user_input = \"Remember my name?\"\n","\n","# The config is the **second positional argument** to stream() or invoke()!\n","events = graph.stream(\n","    {\"messages\": [(\"user\", user_input)]}, config, stream_mode=\"values\"\n",")\n","for event in events:\n","    event[\"messages\"][-1].pretty_print()"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"Er4aAJ3oY7ND","executionInfo":{"status":"ok","timestamp":1721570517010,"user_tz":-480,"elapsed":3252,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"a41a14d5-a214-4c9f-8a5d-5eb278cfb174"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["================================\u001b[1m Human Message \u001b[0m=================================\n","\n","Remember my name?\n","==================================\u001b[1m Ai Message \u001b[0m==================================\n","\n","Yes, I remember your name is Will! How can I help you today?\n"]}]},{"cell_type":"code","source":["# The only difference is we change the `thread_id` here to \"2\" instead of \"1\"\n","events = graph.stream(\n","    {\"messages\": [(\"user\", user_input)]},\n","    {\"configurable\": {\"thread_id\": \"2\"}},\n","    stream_mode=\"values\",\n",")\n","for event in events:\n","    event[\"messages\"][-1].pretty_print()"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"GTdt8MEeZCT5","executionInfo":{"status":"ok","timestamp":1721570550457,"user_tz":-480,"elapsed":2306,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"d93364b4-9776-4e8c-ec7f-9cb13e250ef7"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["================================\u001b[1m Human Message \u001b[0m=================================\n","\n","Remember my name?\n","==================================\u001b[1m Ai Message \u001b[0m==================================\n","\n","I'm sorry, but I don't have the ability to remember personal information about users, including names, between interactions. How can I assist you today?\n"]}]},{"cell_type":"code","source":["snapshot = graph.get_state(config)\n","snapshot"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"lLyW6Bu6ZIT3","executionInfo":{"status":"ok","timestamp":1721570643900,"user_tz":-480,"elapsed":632,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"4f3a9cdd-fe73-473a-a08d-549b25b32064"},"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":["StateSnapshot(values={'messages': [HumanMessage(content='Hi there! My name is Will.', id='e22d6fe9-9b15-4301-a61b-8204ec19f481'), AIMessage(content='Hi Will! How can I assist you today?', response_metadata={'token_usage': {'completion_tokens': 11, 'prompt_tokens': 87, 'total_tokens': 98}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_611b667b19', 'finish_reason': 'stop', 'logprobs': None}, id='run-002be44b-4a1f-4ce9-8562-8198cbbfb921-0', usage_metadata={'input_tokens': 87, 'output_tokens': 11, 'total_tokens': 98}), HumanMessage(content='Remember my name?', id='9f61160c-6f77-4b28-ad68-02f920543844'), AIMessage(content='Yes, I remember your name is Will! How can I help you today?', response_metadata={'token_usage': {'completion_tokens': 17, 'prompt_tokens': 109, 'total_tokens': 126}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_611b667b19', 'finish_reason': 'stop', 'logprobs': None}, id='run-4e99647e-d68b-495d-9916-5bd124dfa62e-0', usage_metadata={'input_tokens': 109, 'output_tokens': 17, 'total_tokens': 126})]}, next=(), config={'configurable': {'thread_id': '1', 'thread_ts': '1ef4769c-9e02-60c6-8004-c41df6116055'}}, metadata={'source': 'loop', 'step': 4, 'writes': {'chatbot': {'messages': [AIMessage(content='Yes, I remember your name is Will! How can I help you today?', response_metadata={'token_usage': {'completion_tokens': 17, 'prompt_tokens': 109, 'total_tokens': 126}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_611b667b19', 'finish_reason': 'stop', 'logprobs': None}, id='run-4e99647e-d68b-495d-9916-5bd124dfa62e-0', usage_metadata={'input_tokens': 109, 'output_tokens': 17, 'total_tokens': 126})]}}}, created_at='2024-07-21T14:01:55.582152+00:00', parent_config={'configurable': {'thread_id': '1', 'thread_ts': '1ef4769c-8d7e-6bcb-8003-a9af85226c8f'}})"]},"metadata":{},"execution_count":28}]},{"cell_type":"code","source":["snapshot.next  # (since the graph ended this turn, `next` is empty. If you fetch a state from within a graph invocation, next tells which node will execute next)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"mZUMHDX6ZYml","executionInfo":{"status":"ok","timestamp":1721570672786,"user_tz":-480,"elapsed":536,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"f61929f1-6dbb-4237-82d8-619415e27ba3"},"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":["()"]},"metadata":{},"execution_count":29}]},{"cell_type":"markdown","source":["# Part 4: 循环中添加人工操作"],"metadata":{"id":"r6TB1BzwlDd4"}},{"cell_type":"code","source":["from typing import Annotated\n","\n","from langchain_community.tools.tavily_search import TavilySearchResults\n","from langchain_core.messages import BaseMessage\n","from typing_extensions import TypedDict\n","from langchain_openai import ChatOpenAI\n","from langgraph.checkpoint.sqlite import SqliteSaver\n","from langgraph.graph import StateGraph\n","from langgraph.graph.message import add_messages\n","from langgraph.prebuilt import ToolNode, tools_condition\n","\n","memory = SqliteSaver.from_conn_string(\":memory:\")\n","\n","\n","class State(TypedDict):\n","    messages: Annotated[list, add_messages]\n","\n","\n","graph_builder = StateGraph(State)\n","\n","\n","tool = TavilySearchResults(max_results=2)\n","tools = [tool]\n","llm = ChatOpenAI(model=\"gpt-4o-mini\", temperature=0)\n","llm_with_tools = llm.bind_tools(tools)\n","\n","\n","def chatbot(state: State):\n","    return {\"messages\": [llm_with_tools.invoke(state[\"messages\"])]}\n","\n","\n","graph_builder.add_node(\"chatbot\", chatbot)\n","\n","tool_node = ToolNode(tools=[tool])\n","graph_builder.add_node(\"tools\", tool_node)\n","\n","graph_builder.add_conditional_edges(\n","    \"chatbot\",\n","    tools_condition,\n",")\n","graph_builder.add_edge(\"tools\", \"chatbot\")\n","graph_builder.set_entry_point(\"chatbot\")"],"metadata":{"id":"Ax_mb1yNZjv2"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["graph = graph_builder.compile(\n","    checkpointer=memory,\n","    # This is new!\n","    interrupt_before=[\"tools\"],\n","    # Note: can also interrupt __after__ actions, if desired.\n","    # interrupt_after=[\"tools\"]\n",")"],"metadata":{"id":"mLDycWsLZyAG"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["user_input = \"I'm learning LangGraph. Could you do some research on it for me?\"\n","config = {\"configurable\": {\"thread_id\": \"1\"}}\n","# The config is the **second positional argument** to stream() or invoke()!\n","events = graph.stream(\n","    {\"messages\": [(\"user\", user_input)]}, config, stream_mode=\"values\"\n",")\n","for event in events:\n","    if \"messages\" in event:\n","        event[\"messages\"][-1].pretty_print()"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"TKOTYTUgZ3F7","executionInfo":{"status":"ok","timestamp":1722133193117,"user_tz":-480,"elapsed":1873,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"57314eeb-743e-41d2-b530-8d5789de55c4"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["================================\u001b[1m Human Message \u001b[0m=================================\n","\n","I'm learning LangGraph. Could you do some research on it for me?\n","==================================\u001b[1m Ai Message \u001b[0m==================================\n","Tool Calls:\n","  tavily_search_results_json (call_nvwGDUrE8oaJRRFnkqC5IJtu)\n"," Call ID: call_nvwGDUrE8oaJRRFnkqC5IJtu\n","  Args:\n","    query: LangGraph tutorial\n"]}]},{"cell_type":"code","source":["snapshot = graph.get_state(config)\n","snapshot.next"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"gw37QKnwaA3f","executionInfo":{"status":"ok","timestamp":1722133262268,"user_tz":-480,"elapsed":525,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"7f846877-ad2b-45d6-f2a7-1357ab0c2bde"},"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":["('tools',)"]},"metadata":{},"execution_count":10}]},{"cell_type":"code","source":["existing_message = snapshot.values[\"messages\"][-1]\n","existing_message.tool_calls"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"XuskVJeyaIB4","executionInfo":{"status":"ok","timestamp":1722133295717,"user_tz":-480,"elapsed":565,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"d9d53d39-e420-4ffd-88eb-8592a6d028f9"},"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":["[{'name': 'tavily_search_results_json',\n","  'args': {'query': 'LangGraph tutorial'},\n","  'id': 'call_nvwGDUrE8oaJRRFnkqC5IJtu',\n","  'type': 'tool_call'}]"]},"metadata":{},"execution_count":11}]},{"cell_type":"code","source":["# `None` will append nothing new to the current state, letting it resume as if it had never been interrupted\n","events = graph.stream(None, config, stream_mode=\"values\")\n","for event in events:\n","    if \"messages\" in event:\n","        event[\"messages\"][-1].pretty_print()"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"7y1moXECaP10","executionInfo":{"status":"ok","timestamp":1722133379747,"user_tz":-480,"elapsed":4433,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"97207cfd-2b21-4755-9f45-4a3c92027520"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["=================================\u001b[1m Tool Message \u001b[0m=================================\n","Name: tavily_search_results_json\n","\n","[{\"url\": \"https://langchain-ai.github.io/langgraphjs/tutorials/\", \"content\": \"Tutorials\\u00b6 Welcome to the LangGraph Tutorials! These notebooks introduce LangGraph through building various language agents and applications. Use cases\\u00b6 Learn from example implementations of graphs designed for specific scenarios and that implement common design patterns. Multi-Agent Systems\\u00b6\"}, {\"url\": \"https://github.com/langchain-ai/langgraph\", \"content\": \"LangGraph is a library for creating stateful, multi-actor applications with LLMs, using cycles, controllability, and persistence. Learn how to use LangGraph with examples, documentation, and integration with LangChain and LangSmith.\"}]\n","==================================\u001b[1m Ai Message \u001b[0m==================================\n","\n","Here are some useful resources about LangGraph:\n","\n","1. **LangGraph Tutorials**: This [tutorial page](https://langchain-ai.github.io/langgraphjs/tutorials/) offers a variety of notebooks that introduce LangGraph through building language agents and applications. It covers various use cases and example implementations that showcase common design patterns.\n","\n","2. **LangGraph GitHub Repository**: The official [LangGraph GitHub repository](https://github.com/langchain-ai/langgraph) provides comprehensive information about the library. It is designed for creating stateful, multi-actor applications with large language models (LLMs). The repository includes documentation, examples, and details on how to integrate LangGraph with LangChain and LangSmith.\n","\n","These resources should help you get started with LangGraph and understand its applications better.\n"]}]},{"cell_type":"markdown","source":["# Part 5: 手动更新状态"],"metadata":{"id":"YbkGtF32BX87"}},{"cell_type":"code","source":["from typing import Annotated\n","\n","from langchain_community.tools.tavily_search import TavilySearchResults\n","from langchain_core.messages import BaseMessage\n","from typing_extensions import TypedDict\n","from langchain_openai import ChatOpenAI\n","from langgraph.checkpoint.sqlite import SqliteSaver\n","from langgraph.graph import StateGraph\n","from langgraph.graph.message import add_messages\n","from langgraph.prebuilt import ToolNode, tools_condition\n","\n","\n","class State(TypedDict):\n","    messages: Annotated[list, add_messages]\n","\n","\n","graph_builder = StateGraph(State)\n","\n","\n","tool = TavilySearchResults(max_results=2)\n","tools = [tool]\n","llm = ChatOpenAI(model=\"gpt-4o-mini\", temperature=0)\n","llm_with_tools = llm.bind_tools(tools)\n","\n","\n","def chatbot(state: State):\n","    return {\"messages\": [llm_with_tools.invoke(state[\"messages\"])]}\n","\n","\n","graph_builder.add_node(\"chatbot\", chatbot)\n","\n","tool_node = ToolNode(tools=[tool])\n","graph_builder.add_node(\"tools\", tool_node)\n","\n","graph_builder.add_conditional_edges(\n","    \"chatbot\",\n","    tools_condition,\n",")\n","graph_builder.add_edge(\"tools\", \"chatbot\")\n","graph_builder.set_entry_point(\"chatbot\")\n","memory = SqliteSaver.from_conn_string(\":memory:\")\n","graph = graph_builder.compile(\n","    checkpointer=memory,\n","    # This is new!\n","    interrupt_before=[\"tools\"],\n","    # Note: can also interrupt **after** actions, if desired.\n","    # interrupt_after=[\"tools\"]\n",")\n","\n","user_input = \"I'm learning LangGraph. Could you do some research on it for me?\"\n","config = {\"configurable\": {\"thread_id\": \"1\"}}\n","# The config is the **second positional argument** to stream() or invoke()!\n","events = graph.stream({\"messages\": [(\"user\", user_input)]}, config)\n","for event in events:\n","    if \"messages\" in event:\n","        event[\"messages\"][-1].pretty_print()"],"metadata":{"id":"gRzAc94xan_j"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["snapshot = graph.get_state(config)\n","existing_message = snapshot.values[\"messages\"][-1]\n","existing_message.pretty_print()"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"Blb7w8WOa4eI","executionInfo":{"status":"ok","timestamp":1722133683663,"user_tz":-480,"elapsed":583,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"036239f1-fbcb-4962-ed20-4a923f5f9b13"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["==================================\u001b[1m Ai Message \u001b[0m==================================\n","Tool Calls:\n","  tavily_search_results_json (call_inoe3ua20K85Zd0QrS5KzFyK)\n"," Call ID: call_inoe3ua20K85Zd0QrS5KzFyK\n","  Args:\n","    query: LangGraph 2023\n"]}]},{"cell_type":"code","source":["from langchain_core.messages import AIMessage\n","from langchain_core.messages import ToolMessage\n","answer = (\n","    \"LangGraph is a library for building stateful, multi-actor applications with LLMs.\"\n",")\n","new_messages = [\n","    # 大模型需要工具的返回 ToolMessage 去完成问题的回答，那我们就模拟一个工具返回。\n","    ToolMessage(content=answer, tool_call_id=existing_message.tool_calls[0][\"id\"]),\n","    # 然后再模拟一个大模型的最终返回 AIMessage，这样就借大模型之口输出了我们定义的答案。\n","    AIMessage(content=answer),\n","]\n","\n","new_messages[-1].pretty_print()\n","graph.update_state(\n","    # 确定更新哪一个状态机 state\n","    config,\n","    # 提供更新的值，state 是只能添加，messages 将被添加到list中\n","    # 为了保存state，下一步我们将查看如何更新现有的messages\n","    {\"messages\": new_messages},\n",")\n","\n","print(\"\\n\\nLast 2 messages;\")\n","print(graph.get_state(config).values[\"messages\"][-2:])"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"BdmzEZr0a_MU","executionInfo":{"status":"ok","timestamp":1722134171942,"user_tz":-480,"elapsed":557,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"6b6ec371-adc3-46ad-c1ed-4c37c0378049"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["==================================\u001b[1m Ai Message \u001b[0m==================================\n","\n","LangGraph is a library for building stateful, multi-actor applications with LLMs.\n","\n","\n","Last 2 messages;\n","[ToolMessage(content='LangGraph is a library for building stateful, multi-actor applications with LLMs.', id='c9b6c1c1-8702-4afa-b881-02670508ca11', tool_call_id='call_inoe3ua20K85Zd0QrS5KzFyK'), AIMessage(content='LangGraph is a library for building stateful, multi-actor applications with LLMs.', id='d443d2b4-1b08-4dcc-9c69-b90e2f1d1a9d')]\n"]}]},{"cell_type":"code","source":["graph.update_state(\n","    config,\n","    {\"messages\": [AIMessage(content=\"I'm an AI expert!\")]},\n","    # Which node for this function to act as. It will automatically continue\n","    # processing as if this node just ran.\n","    as_node=\"chatbot\",\n",")\n","print(\"\\n\\nLast 2 messages;\")\n","print(graph.get_state(config).values[\"messages\"][-2:])"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"gth2PxCUbkIU","executionInfo":{"status":"ok","timestamp":1722134738506,"user_tz":-480,"elapsed":517,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"fd9fde9b-4b17-44be-9bcb-93fe092a0c08"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["\n","\n","Last 2 messages;\n","[AIMessage(content=\"I'm an AI expert!\", id='635d83d7-70f3-47a9-8a23-4200ffe9d2a1'), AIMessage(content=\"I'm an AI expert!\", id='83cea956-2c04-44e1-bf73-9af8ed21d70b')]\n"]}]},{"cell_type":"code","source":["from IPython.display import Image, display\n","\n","try:\n","    display(Image(graph.get_graph().draw_mermaid_png()))\n","except Exception:\n","    # This requires some extra dependencies and is optional\n","    pass"],"metadata":{"colab":{"base_uri":"https://localhost:8080/","height":236},"id":"ihJvhnMTcH8P","executionInfo":{"status":"ok","timestamp":1722134895843,"user_tz":-480,"elapsed":5876,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"8a4d2109-66ce-43c8-eb79-8f2c6052209c"},"execution_count":null,"outputs":[{"output_type":"display_data","data":{"image/jpeg":"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\n","text/plain":["<IPython.core.display.Image object>"]},"metadata":{}}]},{"cell_type":"code","source":["snapshot = graph.get_state(config)\n","print(snapshot.values[\"messages\"][-5:])\n","print(snapshot.next)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"_FcLI9zxcLsK","executionInfo":{"status":"ok","timestamp":1722134924340,"user_tz":-480,"elapsed":608,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"a7a18f09-8e75-45c7-da5c-9ce3e53aca06"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["[AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_inoe3ua20K85Zd0QrS5KzFyK', 'function': {'arguments': '{\"query\":\"LangGraph 2023\"}', 'name': 'tavily_search_results_json'}, 'type': 'function'}]}, response_metadata={'token_usage': {'completion_tokens': 22, 'prompt_tokens': 94, 'total_tokens': 116}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_ba606877f9', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-14fd6df6-3a9d-4b53-8a13-2123f2ad1131-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'LangGraph 2023'}, 'id': 'call_inoe3ua20K85Zd0QrS5KzFyK', 'type': 'tool_call'}], usage_metadata={'input_tokens': 94, 'output_tokens': 22, 'total_tokens': 116}), ToolMessage(content='LangGraph is a library for building stateful, multi-actor applications with LLMs.', id='c9b6c1c1-8702-4afa-b881-02670508ca11', tool_call_id='call_inoe3ua20K85Zd0QrS5KzFyK'), AIMessage(content='LangGraph is a library for building stateful, multi-actor applications with LLMs.', id='d443d2b4-1b08-4dcc-9c69-b90e2f1d1a9d'), AIMessage(content=\"I'm an AI expert!\", id='635d83d7-70f3-47a9-8a23-4200ffe9d2a1'), AIMessage(content=\"I'm an AI expert!\", id='83cea956-2c04-44e1-bf73-9af8ed21d70b')]\n","()\n"]}]},{"cell_type":"markdown","source":["## 重写"],"metadata":{"id":"j4B053JxC2DT"}},{"cell_type":"code","source":["user_input = \"I'm learning LangGraph. Could you do some research on it for me?\"\n","config = {\"configurable\": {\"thread_id\": \"2\"}}  # we'll use thread_id = 2 here\n","events = graph.stream(\n","    {\"messages\": [(\"user\", user_input)]}, config, stream_mode=\"values\"\n",")\n","for event in events:\n","    if \"messages\" in event:\n","        event[\"messages\"][-1].pretty_print()"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"0LvWhuNPcfDB","executionInfo":{"status":"ok","timestamp":1722150341625,"user_tz":-480,"elapsed":1483,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"4cf2f0db-2270-4e8a-e477-425dbb22c7f1"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["================================\u001b[1m Human Message \u001b[0m=================================\n","\n","I'm learning LangGraph. Could you do some research on it for me?\n","==================================\u001b[1m Ai Message \u001b[0m==================================\n","Tool Calls:\n","  tavily_search_results_json (call_VRtPIRhI0hs97UEfWQBqSdEA)\n"," Call ID: call_VRtPIRhI0hs97UEfWQBqSdEA\n","  Args:\n","    query: LangGraph\n"]}]},{"cell_type":"code","source":["from langchain_core.messages import AIMessage\n","\n","snapshot = graph.get_state(config)\n","existing_message = snapshot.values[\"messages\"][-1]\n","print(\"Original\")\n","print(\"Message ID\", existing_message.id)\n","print(existing_message.tool_calls[0])\n","new_tool_call = existing_message.tool_calls[0].copy()\n","new_tool_call[\"args\"][\"query\"] = \"LangGraph human-in-the-loop workflow\"\n","new_message = AIMessage(\n","    content=existing_message.content,\n","    tool_calls=[new_tool_call],\n","    # Important! The ID is how LangGraph knows to REPLACE the message in the state rather than APPEND this messages\n","    id=existing_message.id,\n",")\n","\n","print(\"Updated\")\n","print(new_message.tool_calls[0])\n","print(\"Message ID\", new_message.id)\n","graph.update_state(config, {\"messages\": [new_message]})\n","\n","print(\"\\n\\nTool calls\")\n","graph.get_state(config).values[\"messages\"][-1].tool_calls"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"bkV9BtJ9cjEt","executionInfo":{"status":"ok","timestamp":1722150706743,"user_tz":-480,"elapsed":594,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"b79c05f6-a61e-42a5-d327-fc441cb88af2"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Original\n","Message ID run-6f00d538-e355-4201-b2d8-a400be959539-0\n","{'name': 'tavily_search_results_json', 'args': {'query': 'LangGraph'}, 'id': 'call_VRtPIRhI0hs97UEfWQBqSdEA', 'type': 'tool_call'}\n","Updated\n","{'name': 'tavily_search_results_json', 'args': {'query': 'LangGraph human-in-the-loop workflow'}, 'id': 'call_VRtPIRhI0hs97UEfWQBqSdEA', 'type': 'tool_call'}\n","Message ID run-6f00d538-e355-4201-b2d8-a400be959539-0\n","\n","\n","Tool calls\n"]},{"output_type":"execute_result","data":{"text/plain":["[{'name': 'tavily_search_results_json',\n","  'args': {'query': 'LangGraph human-in-the-loop workflow'},\n","  'id': 'call_VRtPIRhI0hs97UEfWQBqSdEA',\n","  'type': 'tool_call'}]"]},"metadata":{},"execution_count":7}]},{"cell_type":"code","source":["events = graph.stream(None, config, stream_mode=\"values\")\n","for event in events:\n","    if \"messages\" in event:\n","        event[\"messages\"][-1].pretty_print()"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"3j3GQYRhc92d","executionInfo":{"status":"ok","timestamp":1722150784171,"user_tz":-480,"elapsed":5620,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"c2a32d82-e9f2-4b6d-a6d3-8f8e6588fd40"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["=================================\u001b[1m Tool Message \u001b[0m=================================\n","Name: tavily_search_results_json\n","\n","[{\"url\": \"https://blog.langchain.dev/how-to-build-the-ultimate-ai-automation-with-multi-agent-collaboration/\", \"content\": \"from langgraph.graph import StateGraph workflow = StateGraph(ResearchState) ... Human in the loop is key for optimized AI experiences. Having a human help the assistant revise and focus on just the right research plan, topics and outline, would enhance the overall quality and experience. In addition, aiming for relying on human intervention ...\"}, {\"url\": \"https://www.youtube.com/watch?v=9BPCV5TYPmg\", \"content\": \"In this video, I'll show you how to handle persistence with LangGraph, enabling a unique Human-in-the-Loop workflow. This approach allows a human to grant an...\"}]\n","==================================\u001b[1m Ai Message \u001b[0m==================================\n","\n","Here's some information about LangGraph and its applications, particularly in the context of human-in-the-loop workflows:\n","\n","1. **LangGraph Overview**: LangGraph is a tool designed to assist developers in building AI applications that involve complex workflows and state management. It enables the creation of dynamic graphs representing states and transitions in a workflow.\n","\n","2. **Human-in-the-Loop Workflows**: One significant aspect of LangGraph is its support for human-in-the-loop workflows. This approach is essential for optimizing AI experiences by allowing human intervention at critical stages. For instance, in research or planning scenarios, a human can help refine and focus the AI's suggestions, enhancing the quality of the outcomes.\n","\n","3. **Example Application**: A practical example from the LangChain blog illustrates how to leverage LangGraph to build AI automation with multi-agent collaboration. You can create a `StateGraph` that allows for various states in a workflow where humans can guide and make decisions based on AI outputs.\n","\n","4. **Resource Links**:\n","   - [Blog on AI Automation with LangGraph](https://blog.langchain.dev/how-to-build-the-ultimate-ai-automation-with-multi-agent-collaboration/)\n","   - [YouTube Video on Persistence with LangGraph](https://www.youtube.com/watch?v=9BPCV5TYPmg)\n","\n","These resources should provide a good starting point for your learning. If you need more specific information about LangGraph, just let me know!\n"]}]},{"cell_type":"code","source":["events = graph.stream(\n","    {\n","        \"messages\": (\n","            \"user\",\n","            \"Remember what I'm learning about?\",\n","        )\n","    },\n","    config,\n","    stream_mode=\"values\",\n",")\n","for event in events:\n","    if \"messages\" in event:\n","        event[\"messages\"][-1].pretty_print()"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"-9qxHIINdaPx","executionInfo":{"status":"ok","timestamp":1722150938096,"user_tz":-480,"elapsed":2117,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"03d067d0-6cbe-48e4-ab9b-408a8fa07648"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["================================\u001b[1m Human Message \u001b[0m=================================\n","\n","Remember what I'm learning about?\n","==================================\u001b[1m Ai Message \u001b[0m==================================\n","\n","Yes, you're learning about LangGraph, particularly its applications and features related to human-in-the-loop workflows. If you have specific questions or topics you want to explore further about LangGraph, feel free to let me know!\n"]}]},{"cell_type":"markdown","source":["# Part 6: 自定义状态"],"metadata":{"id":"M6aFoDvFD0ty"}},{"cell_type":"code","source":["from typing import Annotated\n","\n","from langchain_community.tools.tavily_search import TavilySearchResults\n","from langchain_core.messages import BaseMessage\n","from typing_extensions import TypedDict\n","\n","from langgraph.checkpoint.sqlite import SqliteSaver\n","from langgraph.graph import StateGraph\n","from langgraph.graph.message import add_messages\n","from langgraph.prebuilt import ToolNode, tools_condition\n","\n","\n","class State(TypedDict):\n","    messages: Annotated[list, add_messages]\n","    # This flag is new\n","    ask_human: bool"],"metadata":{"id":"XnN9Y8OFdtXI"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["from langchain_core.pydantic_v1 import BaseModel\n","\n","\n","class RequestAssistance(BaseModel):\n","    \"\"\"Escalate the conversation to an expert. Use this if you are unable to assist directly or if the user requires support beyond your permissions.\n","\n","    To use this function, relay the user's 'request' so the expert can provide the right guidance.\n","    \"\"\"\n","\n","    request: str"],"metadata":{"id":"KOjkyW2xd0mL"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["tool = TavilySearchResults(max_results=2)\n","tools = [tool]\n","llm = ChatOpenAI(model=\"gpt-4o-mini\", temperature=0)\n","# We can bind the llm to a tool definition, a pydantic model, or a json schema\n","llm_with_tools = llm.bind_tools(tools + [RequestAssistance])\n","\n","\n","def chatbot(state: State):\n","    response = llm_with_tools.invoke(state[\"messages\"])\n","    ask_human = False\n","    if (\n","        response.tool_calls\n","        and response.tool_calls[0][\"name\"] == RequestAssistance.__name__\n","    ):\n","        ask_human = True\n","    return {\"messages\": [response], \"ask_human\": ask_human}"],"metadata":{"id":"IuGs_mFad4hl"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["graph_builder = StateGraph(State)\n","\n","graph_builder.add_node(\"chatbot\", chatbot)\n","graph_builder.add_node(\"tools\", ToolNode(tools=[tool]))"],"metadata":{"id":"1RUGBjqnemzh"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["from langchain_core.messages import AIMessage, ToolMessage\n","\n","\n","def create_response(response: str, ai_message: AIMessage):\n","    return ToolMessage(\n","        content=response,\n","        tool_call_id=ai_message.tool_calls[0][\"id\"],\n","    )\n","\n","\n","def human_node(state: State):\n","    new_messages = []\n","    if not isinstance(state[\"messages\"][-1], ToolMessage):\n","        # Typically, the user will have updated the state during the interrupt.\n","        # If they choose not to, we will include a placeholder ToolMessage to\n","        # let the LLM continue.\n","        new_messages.append(\n","            create_response(\"No response from human.\", state[\"messages\"][-1])\n","        )\n","    return {\n","        # Append the new messages\n","        \"messages\": new_messages,\n","        # Unset the flag\n","        \"ask_human\": False,\n","    }\n","\n","\n","graph_builder.add_node(\"human\", human_node)"],"metadata":{"id":"cQtdoyI8eq6r"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["def select_next_node(state: State):\n","    if state[\"ask_human\"]:\n","        return \"human\"\n","    # Otherwise, we can route as before\n","    return tools_condition(state)\n","\n","\n","graph_builder.add_conditional_edges(\n","    \"chatbot\",\n","    select_next_node,\n","    {\"human\": \"human\", \"tools\": \"tools\", \"__end__\": \"__end__\"},\n",")"],"metadata":{"collapsed":true,"id":"RfU3x-xEe3Jh"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["# The rest is the same\n","graph_builder.add_edge(\"tools\", \"chatbot\")\n","graph_builder.add_edge(\"human\", \"chatbot\")\n","graph_builder.set_entry_point(\"chatbot\")\n","memory = SqliteSaver.from_conn_string(\":memory:\")\n","graph = graph_builder.compile(\n","    checkpointer=memory,\n","    # We interrupt before 'human' here instead.\n","    interrupt_before=[\"human\"],\n",")"],"metadata":{"id":"hG9eZd8SfD7g"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["from IPython.display import Image, display\n","\n","try:\n","    display(Image(graph.get_graph().draw_mermaid_png()))\n","except Exception:\n","    # This requires some extra dependencies and is optional\n","    pass"],"metadata":{"colab":{"base_uri":"https://localhost:8080/","height":236},"id":"pzI_hAXTfLA7","executionInfo":{"status":"ok","timestamp":1722152269592,"user_tz":-480,"elapsed":1329,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"ea86d8e6-ebc8-421f-fb16-1751f78262f2"},"execution_count":null,"outputs":[{"output_type":"display_data","data":{"image/jpeg":"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\n","text/plain":["<IPython.core.display.Image object>"]},"metadata":{}}]},{"cell_type":"code","source":["user_input = \"I need some expert guidance for building this AI agent. Could you request assistance for me?\"\n","config = {\"configurable\": {\"thread_id\": \"1\"}}\n","# The config is the **second positional argument** to stream() or invoke()!\n","events = graph.stream(\n","    {\"messages\": [(\"user\", user_input)]}, config, stream_mode=\"values\"\n",")\n","for event in events:\n","    if \"messages\" in event:\n","        event[\"messages\"][-1].pretty_print()"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"_dDWLGrbfS6X","executionInfo":{"status":"ok","timestamp":1722152359689,"user_tz":-480,"elapsed":2938,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"e2f96e1d-31c0-485b-d451-a79f0baf5bdb"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["================================\u001b[1m Human Message \u001b[0m=================================\n","\n","I need some expert guidance for building this AI agent. Could you request assistance for me?\n","==================================\u001b[1m Ai Message \u001b[0m==================================\n","Tool Calls:\n","  RequestAssistance (call_J0bMfTwKP1jm4bZ903A16SIf)\n"," Call ID: call_J0bMfTwKP1jm4bZ903A16SIf\n","  Args:\n","    request: I need expert guidance on building an AI agent. I'm looking for information on best practices, tools, and resources for developing its capabilities.\n"]}]},{"cell_type":"code","source":["snapshot = graph.get_state(config)\n","snapshot.next"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"8ksEWkVofaLd","executionInfo":{"status":"ok","timestamp":1722152405400,"user_tz":-480,"elapsed":522,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"49923fd7-5f88-43bc-9092-124da5b88e93"},"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":["('human',)"]},"metadata":{},"execution_count":20}]},{"cell_type":"code","source":["ai_message = snapshot.values[\"messages\"][-1]\n","human_response = (\n","    \"We, the experts are here to help! We'd recommend you check out LangGraph to build your agent.\"\n","    \" It's much more reliable and extensible than simple autonomous agents.\"\n",")\n","tool_message = create_response(human_response, ai_message)\n","graph.update_state(config, {\"messages\": [tool_message]})"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"vHuFcTezfgDy","executionInfo":{"status":"ok","timestamp":1722152563047,"user_tz":-480,"elapsed":627,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"41bf949d-59db-45f6-ff48-a07a9a864eed"},"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":["{'configurable': {'thread_id': '1',\n","  'thread_ts': '1ef4cb4f-7ddd-60da-8002-117bb12087c2'}}"]},"metadata":{},"execution_count":21}]},{"cell_type":"code","source":["graph.get_state(config).values[\"messages\"]"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"DRkWqWXJhOiS","executionInfo":{"status":"ok","timestamp":1722152592533,"user_tz":-480,"elapsed":563,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"ba25f293-f36f-4139-98f3-268470b3b84b"},"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":["[HumanMessage(content='I need some expert guidance for building this AI agent. Could you request assistance for me?', id='6a67f8f7-15e0-4142-a5ee-e8aa845096b1'),\n"," AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_J0bMfTwKP1jm4bZ903A16SIf', 'function': {'arguments': '{\"request\":\"I need expert guidance on building an AI agent. I\\'m looking for information on best practices, tools, and resources for developing its capabilities.\"}', 'name': 'RequestAssistance'}, 'type': 'function'}]}, response_metadata={'token_usage': {'completion_tokens': 41, 'prompt_tokens': 160, 'total_tokens': 201}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_611b667b19', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-09c9e36a-8685-435b-9e64-50fbc8e53b1b-0', tool_calls=[{'name': 'RequestAssistance', 'args': {'request': \"I need expert guidance on building an AI agent. I'm looking for information on best practices, tools, and resources for developing its capabilities.\"}, 'id': 'call_J0bMfTwKP1jm4bZ903A16SIf', 'type': 'tool_call'}], usage_metadata={'input_tokens': 160, 'output_tokens': 41, 'total_tokens': 201}),\n"," ToolMessage(content=\"We, the experts are here to help! We'd recommend you check out LangGraph to build your agent. It's much more reliable and extensible than simple autonomous agents.\", id='a5e85277-fb7f-46ed-ba60-101f910c8203', tool_call_id='call_J0bMfTwKP1jm4bZ903A16SIf')]"]},"metadata":{},"execution_count":22}]},{"cell_type":"code","source":["events = graph.stream(None, config, stream_mode=\"values\")\n","for event in events:\n","    if \"messages\" in event:\n","        event[\"messages\"][-1].pretty_print()"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"kZbg9wZ-hjMJ","executionInfo":{"status":"ok","timestamp":1722152657987,"user_tz":-480,"elapsed":3550,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"2bf447fc-4aa2-4e15-85cd-4d8ec62ac943"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["=================================\u001b[1m Tool Message \u001b[0m=================================\n","\n","We, the experts are here to help! We'd recommend you check out LangGraph to build your agent. It's much more reliable and extensible than simple autonomous agents.\n","==================================\u001b[1m Ai Message \u001b[0m==================================\n","\n","I've reached out for expert guidance, and they recommended using **LangGraph** for building your AI agent. It is considered more reliable and extensible compared to simpler autonomous agents. If you have any specific areas you'd like to explore further or questions about LangGraph, feel free to ask!\n"]}]},{"cell_type":"markdown","source":["# Part 7: 执行回退"],"metadata":{"id":"1Br69BzfY_TB"}},{"cell_type":"code","source":["from typing import Annotated, Literal\n","\n","from langchain_openai import ChatOpenAI\n","from langchain_community.tools.tavily_search import TavilySearchResults\n","from langchain_core.messages import AIMessage, BaseMessage, ToolMessage\n","from langchain_core.pydantic_v1 import BaseModel\n","from typing_extensions import TypedDict\n","from langgraph.checkpoint.sqlite import SqliteSaver\n","from langgraph.graph import StateGraph\n","from langgraph.graph.message import add_messages\n","from langgraph.prebuilt import ToolNode, tools_condition\n","\n","\n","class State(TypedDict):\n","    messages: Annotated[list, add_messages]\n","    # This flag is new\n","    ask_human: bool\n","\n","\n","class RequestAssistance(BaseModel):\n","    \"\"\"Escalate the conversation to an expert. Use this if you are unable to assist directly or if the user requires support beyond your permissions.\n","\n","    To use this function, relay the user's 'request' so the expert can provide the right guidance.\n","    \"\"\"\n","\n","    request: str\n","\n","\n","tool = TavilySearchResults(max_results=2)\n","tools = [tool]\n","llm = ChatOpenAI(model=\"gpt-4o-mini\", temperature=0)\n","# We can bind the llm to a tool definition, a pydantic model, or a json schema\n","llm_with_tools = llm.bind_tools(tools + [RequestAssistance])\n","\n","\n","def chatbot(state: State):\n","    response = llm_with_tools.invoke(state[\"messages\"])\n","    ask_human = False\n","    if (\n","        response.tool_calls\n","        and response.tool_calls[0][\"name\"] == RequestAssistance.__name__\n","    ):\n","        ask_human = True\n","    return {\"messages\": [response], \"ask_human\": ask_human}\n","\n","\n","graph_builder = StateGraph(State)\n","\n","graph_builder.add_node(\"chatbot\", chatbot)\n","graph_builder.add_node(\"tools\", ToolNode(tools=[tool]))\n","\n","\n","def create_response(response: str, ai_message: AIMessage):\n","    return ToolMessage(\n","        content=response,\n","        tool_call_id=ai_message.tool_calls[0][\"id\"],\n","    )\n","\n","\n","def human_node(state: State):\n","    new_messages = []\n","    if not isinstance(state[\"messages\"][-1], ToolMessage):\n","        # Typically, the user will have updated the state during the interrupt.\n","        # If they choose not to, we will include a placeholder ToolMessage to\n","        # let the LLM continue.\n","        new_messages.append(\n","            create_response(\"No response from human.\", state[\"messages\"][-1])\n","        )\n","    return {\n","        # Append the new messages\n","        \"messages\": new_messages,\n","        # Unset the flag\n","        \"ask_human\": False,\n","    }\n","\n","\n","graph_builder.add_node(\"human\", human_node)\n","\n","\n","def select_next_node(state: State) -> Literal[\"human\", \"tools\", \"__end__\"]:\n","    if state[\"ask_human\"]:\n","        return \"human\"\n","    # Otherwise, we can route as before\n","    return tools_condition(state)\n","\n","\n","graph_builder.add_conditional_edges(\n","    \"chatbot\",\n","    select_next_node,\n","    {\"human\": \"human\", \"tools\": \"tools\", \"__end__\": \"__end__\"},\n",")\n","graph_builder.add_edge(\"tools\", \"chatbot\")\n","graph_builder.add_edge(\"human\", \"chatbot\")\n","graph_builder.set_entry_point(\"chatbot\")\n","memory = SqliteSaver.from_conn_string(\":memory:\")\n","graph = graph_builder.compile(\n","    checkpointer=memory,\n","    interrupt_before=[\"human\"],\n",")"],"metadata":{"id":"arN1upeBaXeg"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["from IPython.display import Image, display\n","\n","try:\n","    display(Image(graph.get_graph().draw_mermaid_png()))\n","except Exception:\n","    # This requires some extra dependencies and is optional\n","    pass"],"metadata":{"colab":{"base_uri":"https://localhost:8080/","height":236},"id":"BR0S2gjdaa9A","executionInfo":{"status":"ok","timestamp":1722152986501,"user_tz":-480,"elapsed":1964,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"63be5d84-c85d-4357-80fe-f883a2527543"},"execution_count":null,"outputs":[{"output_type":"display_data","data":{"image/jpeg":"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\n","text/plain":["<IPython.core.display.Image object>"]},"metadata":{}}]},{"cell_type":"code","source":["config = {\"configurable\": {\"thread_id\": \"1\"}}\n","events = graph.stream(\n","    {\n","        \"messages\": [\n","            (\"user\", \"I'm learning LangGraph. Could you do some research on it for me?\")\n","        ]\n","    },\n","    config,\n","    stream_mode=\"values\",\n",")\n","for event in events:\n","    if \"messages\" in event:\n","        event[\"messages\"][-1].pretty_print()"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"xuW93q91afjU","executionInfo":{"status":"ok","timestamp":1722153022305,"user_tz":-480,"elapsed":6782,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"cce83107-4d07-4fc8-cd4c-0f8933047e2d"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["================================\u001b[1m Human Message \u001b[0m=================================\n","\n","I'm learning LangGraph. Could you do some research on it for me?\n","==================================\u001b[1m Ai Message \u001b[0m==================================\n","Tool Calls:\n","  tavily_search_results_json (call_Fuw8BC0IiVdRAih1xzRt5ito)\n"," Call ID: call_Fuw8BC0IiVdRAih1xzRt5ito\n","  Args:\n","    query: LangGraph\n","=================================\u001b[1m Tool Message \u001b[0m=================================\n","Name: tavily_search_results_json\n","\n","[{\"url\": \"https://blog.langchain.dev/langgraph-cloud/\", \"content\": \"LangGraph is a framework for building agentic and multi-agent applications with LLMs, and LangGraph Cloud is a scalable and reliable infrastructure for deploying them. Learn how LangGraph helps you design, debug, and monitor complex agentic workflows with LLMs.\"}, {\"url\": \"https://github.com/langchain-ai/langgraph\", \"content\": \"LangGraph is a library for creating stateful, multi-actor applications with LLMs, using cycles, controllability, and persistence. Learn how to use LangGraph with examples, integration with LangChain, and streaming support.\"}]\n","==================================\u001b[1m Ai Message \u001b[0m==================================\n","\n","Here are some resources that provide insight into LangGraph:\n","\n","1. **LangGraph Overview**: LangGraph is a framework designed for building agentic and multi-agent applications utilizing large language models (LLMs). It provides a scalable and reliable infrastructure via LangGraph Cloud, allowing users to design, debug, and monitor complex agentic workflows effectively. You can read more about it in this [blog post on LangChain](https://blog.langchain.dev/langgraph-cloud/).\n","\n","2. **LangGraph GitHub Repository**: The GitHub repository for LangGraph offers detailed information about creating stateful, multi-actor applications with LLMs. It emphasizes features like cycles, controllability, and persistence. The repository also includes usage examples, integration with LangChain, and support for streaming. Visit the repository [here](https://github.com/langchain-ai/langgraph).\n","\n","Feel free to explore these resources to further your understanding of LangGraph!\n"]}]},{"cell_type":"code","source":["events = graph.stream(\n","    {\n","        \"messages\": [\n","            (\"user\", \"Ya that's helpful. Maybe I'll build an autonomous agent with it!\")\n","        ]\n","    },\n","    config,\n","    stream_mode=\"values\",\n",")\n","for event in events:\n","    if \"messages\" in event:\n","        event[\"messages\"][-1].pretty_print()"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"ZvGu1NNaaiWc","executionInfo":{"status":"ok","timestamp":1722153098179,"user_tz":-480,"elapsed":3978,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"05f2aee9-4fd0-46d0-9249-ffb0da99db1f"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["================================\u001b[1m Human Message \u001b[0m=================================\n","\n","Ya that's helpful. Maybe I'll build an autonomous agent with it!\n","==================================\u001b[1m Ai Message \u001b[0m==================================\n","\n","That sounds like an exciting project! Building an autonomous agent with LangGraph could offer you a lot of flexibility and control, especially with its capabilities for managing multi-agent applications and workflows. If you have any specific questions as you dive into the development process or need tips, feel free to ask! Good luck with your project!\n"]}]},{"cell_type":"code","source":["events = graph.stream(\n","    {\n","        \"messages\": [\n","            (\"user\", \"can you help me?\")\n","        ]\n","    },\n","    config,\n","    stream_mode=\"values\",\n",")\n","for event in events:\n","    if \"messages\" in event:\n","        event[\"messages\"][-1].pretty_print()"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"980mYtE5apJB","executionInfo":{"status":"ok","timestamp":1722153105804,"user_tz":-480,"elapsed":2002,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"0fe21f3c-1cf8-491a-e057-c1d6ec049d76"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["================================\u001b[1m Human Message \u001b[0m=================================\n","\n","can you help me?\n","==================================\u001b[1m Ai Message \u001b[0m==================================\n","\n","Of course! What do you need help with? Whether it's a question about LangGraph, building your autonomous agent, or anything else, feel free to share!\n"]}]},{"cell_type":"code","source":["to_replay = None\n","for state in graph.get_state_history(config):\n","    print(\"Num Messages: \", len(state.values[\"messages\"]), \"Next: \", state.next)\n","    print(\"-\" * 80)\n","    if len(state.values[\"messages\"]) == 5:\n","        # 然后我们根据state包含的记录条数退回到第6步\n","       to_replay = state\n"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"4D0RhaSEa65-","executionInfo":{"status":"ok","timestamp":1722153158885,"user_tz":-480,"elapsed":570,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"ace2d713-fb09-415c-8d35-5d3a548a7ebf"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Num Messages:  8 Next:  ()\n","--------------------------------------------------------------------------------\n","Num Messages:  7 Next:  ('chatbot',)\n","--------------------------------------------------------------------------------\n","Num Messages:  6 Next:  ('__start__',)\n","--------------------------------------------------------------------------------\n","Num Messages:  6 Next:  ()\n","--------------------------------------------------------------------------------\n","Num Messages:  5 Next:  ('chatbot',)\n","--------------------------------------------------------------------------------\n","Num Messages:  4 Next:  ('__start__',)\n","--------------------------------------------------------------------------------\n","Num Messages:  4 Next:  ()\n","--------------------------------------------------------------------------------\n","Num Messages:  3 Next:  ('chatbot',)\n","--------------------------------------------------------------------------------\n","Num Messages:  2 Next:  ('tools',)\n","--------------------------------------------------------------------------------\n","Num Messages:  1 Next:  ('chatbot',)\n","--------------------------------------------------------------------------------\n","Num Messages:  0 Next:  ('__start__',)\n","--------------------------------------------------------------------------------\n"]}]},{"cell_type":"code","source":["for state in graph.get_state_history(config):\n","    if len(state.values[\"messages\"]) == 2:\n","        # 然后我们根据state包含的记录条数退回到第2步\n","       to_replay = state"],"metadata":{"id":"v4tOg_MgVmuq"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["print(to_replay.next)\n","print(to_replay.config)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"AFexhcN_bCmC","executionInfo":{"status":"ok","timestamp":1722153446474,"user_tz":-480,"elapsed":4,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"f682fc02-e196-4d6d-f85f-b6423a3dc6d3"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["('tools',)\n","{'configurable': {'thread_id': '1', 'thread_ts': '1ef4cb60-68ee-6aab-8001-babe61399c58'}}\n"]}]},{"cell_type":"code","source":["# The `thread_ts` in the `to_replay.config` corresponds to a state we've persisted to our checkpointer.\n","for event in graph.stream(None, to_replay.config, stream_mode=\"values\"):\n","    if \"messages\" in event:\n","        event[\"messages\"][-1].pretty_print()\n"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"sop-tIyMbQp6","executionInfo":{"status":"ok","timestamp":1722153568297,"user_tz":-480,"elapsed":11094,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"f3c72961-84a6-4799-b8dd-041268a2ab19"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["=================================\u001b[1m Tool Message \u001b[0m=================================\n","Name: tavily_search_results_json\n","\n","[{\"url\": \"https://blog.langchain.dev/langgraph-cloud/\", \"content\": \"LangGraph is a framework for building agentic and multi-agent applications with LLMs, and LangGraph Cloud is a scalable and reliable infrastructure for deploying them. Learn how LangGraph helps you design, debug, and monitor complex agentic workflows with LLMs.\"}, {\"url\": \"https://github.com/langchain-ai/langgraph\", \"content\": \"LangGraph is a library for creating stateful, multi-actor applications with LLMs, using cycles, controllability, and persistence. Learn how to use LangGraph with examples, integration with LangChain, and streaming support.\"}]\n","==================================\u001b[1m Ai Message \u001b[0m==================================\n","\n","LangGraph is a framework designed for building multi-agent applications using large language models (LLMs). Here are some key insights from the research:\n","\n","1. **Framework Overview**:\n","   - LangGraph allows developers to create agentic and multi-agent applications. It emphasizes designing, debugging, and monitoring complex workflows that utilize LLMs.\n","\n","2. **Cloud Infrastructure**:\n","   - LangGraph Cloud provides a scalable and reliable infrastructure for deploying these applications, ensuring that they can manage and execute agentic workflows effectively.\n","\n","3. **Library Features**:\n","   - The LangGraph library is specifically crafted for creating stateful, multi-actor applications. It includes features for cycles, controllability, and persistence. This allows for a robust application development experience with LLMs.\n","\n","4. **Integration and Example Use**:\n","   - There are resources available that detail how to use LangGraph, including integration with LangChain and support for streaming.\n","\n","For more detailed information, you can check out the following resources:\n","- [LangGraph Cloud Overview](https://blog.langchain.dev/langgraph-cloud/)\n","- [LangGraph GitHub Repository](https://github.com/langchain-ai/langgraph)\n","\n","If you have any specific questions or need further information on a particular aspect of LangGraph, feel free to ask!\n"]}]},{"cell_type":"code","source":["snapshot = graph.get_state(config)\n","snapshot.next"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"y93vPosqbuKq","executionInfo":{"status":"ok","timestamp":1722153731697,"user_tz":-480,"elapsed":702,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"d0deaece-371e-44dc-a131-c131ae2b6fd0"},"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":["()"]},"metadata":{},"execution_count":34}]}]}